Merge pull request #2235 from brauner/2018-03-25/simplify_autodev

conf: simplify autodev
This commit is contained in:
Stéphane Graber 2018-03-25 22:30:58 -04:00 committed by GitHub
commit 065d5d0d3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1203,28 +1203,28 @@ static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs,
return 0; return 0;
} }
struct lxc_devs { struct lxc_device_node {
const char *name; const char *name;
mode_t mode; const mode_t mode;
int maj; const int maj;
int min; const int min;
}; };
static const struct lxc_devs lxc_devs[] = { static const struct lxc_device_node lxc_devices[] = {
{ "null", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 3 },
{ "zero", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 5 },
{ "full", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 7 }, { "full", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 7 },
{ "urandom", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 9 }, { "null", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 3 },
{ "random", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 8 }, { "random", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 8 },
{ "tty", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 5, 0 }, { "tty", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 5, 0 },
{ "urandom", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 9 },
{ "zero", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 5 },
}; };
static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
{ {
int ret; int i, ret;
char path[MAXPATHLEN]; char path[MAXPATHLEN];
int i;
mode_t cmask; mode_t cmask;
bool can_mknod = true;
ret = snprintf(path, MAXPATHLEN, "%s/dev", ret = snprintf(path, MAXPATHLEN, "%s/dev",
rootfs->path ? rootfs->mount : ""); rootfs->path ? rootfs->mount : "");
@ -1238,53 +1238,55 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
INFO("Populating \"/dev\""); INFO("Populating \"/dev\"");
cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH); cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH);
for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) { for (i = 0; i < sizeof(lxc_devices) / sizeof(lxc_devices[0]); i++) {
const struct lxc_devs *d = &lxc_devs[i]; char hostpath[MAXPATHLEN];
const struct lxc_device_node *device = &lxc_devices[i];
ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", ret = snprintf(path, MAXPATHLEN, "%s/dev/%s",
rootfs->path ? rootfs->mount : "", d->name); rootfs->path ? rootfs->mount : "", device->name);
if (ret < 0 || ret >= MAXPATHLEN) if (ret < 0 || ret >= MAXPATHLEN)
return -1; return -1;
ret = mknod(path, d->mode, makedev(d->maj, d->min)); if (can_mknod) {
if (ret < 0) { ret = mknod(path, device->mode, makedev(device->maj, device->min));
FILE *pathfile; if (ret == 0 || (ret < 0 && errno == EEXIST)) {
char hostpath[MAXPATHLEN]; DEBUG("Created device node \"%s\"", path);
if (errno == EEXIST) {
DEBUG("\"%s\" device already existed", path);
continue; continue;
} }
/* Unprivileged containers cannot create devices, so if (errno != EPERM) {
* bind mount the device from the host. SYSERROR("Failed to create device node \"%s\"", path);
*/
ret = snprintf(hostpath, MAXPATHLEN, "/dev/%s", d->name);
if (ret < 0 || ret >= MAXPATHLEN)
return -1; return -1;
}
pathfile = fopen(path, "wb"); /* This can e.g. happen when the container is
if (!pathfile) { * unprivileged or CAP_MKNOD has been dropped.
*/
can_mknod = false;
}
ret = mknod(path, S_IFREG, 0);
if (ret < 0 && errno != EEXIST) {
SYSERROR("Failed to create file \"%s\"", path); SYSERROR("Failed to create file \"%s\"", path);
return -1; return -1;
} }
fclose(pathfile);
/* Fallback to bind-mounting the device from the host. */
ret = snprintf(hostpath, MAXPATHLEN, "/dev/%s", device->name);
if (ret < 0 || ret >= MAXPATHLEN)
return -1;
ret = safe_mount(hostpath, path, 0, MS_BIND, NULL, ret = safe_mount(hostpath, path, 0, MS_BIND, NULL,
rootfs->path ? rootfs->mount : NULL); rootfs->path ? rootfs->mount : NULL);
if (ret < 0) { if (ret < 0) {
SYSERROR("Failed to bind mount \"%s\" from " SYSERROR("Failed to bind mount host device node \"%s\" "
"host into container", "onto \"%s\"", hostpath, path);
d->name);
return -1; return -1;
} }
DEBUG("Bind mounted \"%s\" onto \"%s\"", hostpath, DEBUG("Bind mounted host device node \"%s\" onto \"%s\"",
path); hostpath, path);
} else {
DEBUG("Created device node \"%s\"", path);
} }
} (void)umask(cmask);
umask(cmask);
INFO("Populated \"/dev\""); INFO("Populated \"/dev\"");
return 0; return 0;