From 2df1b5ca57592e3c8d88c59dac7717aebc34aeb4 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Sun, 25 Mar 2018 14:33:44 +0200 Subject: [PATCH] conf: simplify lxc_fill_autodev() This function was way more syscall heavy than it needed to be. Signed-off-by: Christian Brauner --- src/lxc/conf.c | 90 ++++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index cf3c8a7ce..7ddfbe21b 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -1033,28 +1033,28 @@ static int mount_autodev(const char *name, const struct lxc_rootfs *rootfs, return 0; } -struct lxc_devs { +struct lxc_device_node { const char *name; - mode_t mode; - int maj; - int min; + const mode_t mode; + const int maj; + const int min; }; -static const struct lxc_devs lxc_devs[] = { - { "null", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 3 }, - { "zero", S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 5 }, +static const struct lxc_device_node lxc_devices[] = { { "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 }, { "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) { - int ret; + int i, ret; char path[MAXPATHLEN]; - int i; mode_t cmask; + bool can_mknod = true; ret = snprintf(path, MAXPATHLEN, "%s/dev", rootfs->path ? rootfs->mount : ""); @@ -1068,53 +1068,55 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) INFO("Populating \"/dev\""); cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH); - for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) { - const struct lxc_devs *d = &lxc_devs[i]; + for (i = 0; i < sizeof(lxc_devices) / sizeof(lxc_devices[0]); i++) { + char hostpath[MAXPATHLEN]; + const struct lxc_device_node *device = &lxc_devices[i]; ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", - rootfs->path ? rootfs->mount : "", d->name); + rootfs->path ? rootfs->mount : "", device->name); if (ret < 0 || ret >= MAXPATHLEN) return -1; - ret = mknod(path, d->mode, makedev(d->maj, d->min)); - if (ret < 0) { - FILE *pathfile; - char hostpath[MAXPATHLEN]; - - if (errno == EEXIST) { - DEBUG("\"%s\" device already existed", path); + if (can_mknod) { + ret = mknod(path, device->mode, makedev(device->maj, device->min)); + if (ret == 0 || (ret < 0 && errno == EEXIST)) { + DEBUG("Created device node \"%s\"", path); continue; } - /* Unprivileged containers cannot create devices, so - * bind mount the device from the host. - */ - ret = snprintf(hostpath, MAXPATHLEN, "/dev/%s", d->name); - if (ret < 0 || ret >= MAXPATHLEN) - return -1; - - pathfile = fopen(path, "wb"); - if (!pathfile) { - SYSERROR("Failed to create file \"%s\"", path); + if (errno != EPERM) { + SYSERROR("Failed to create device node \"%s\"", path); return -1; } - fclose(pathfile); - ret = safe_mount(hostpath, path, 0, MS_BIND, NULL, - rootfs->path ? rootfs->mount : NULL); - if (ret < 0) { - SYSERROR("Failed to bind mount \"%s\" from " - "host into container", - d->name); - return -1; - } - DEBUG("Bind mounted \"%s\" onto \"%s\"", hostpath, - path); - } else { - DEBUG("Created device node \"%s\"", path); + /* This can e.g. happen when the container is + * 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); + return -1; + } + + /* 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, + rootfs->path ? rootfs->mount : NULL); + if (ret < 0) { + SYSERROR("Failed to bind mount host device node \"%s\" " + "onto \"%s\"", hostpath, path); + return -1; } + DEBUG("Bind mounted host device node \"%s\" onto \"%s\"", + hostpath, path); } - umask(cmask); + (void)umask(cmask); INFO("Populated \"/dev\""); return 0; -- 2.47.2