Control: tags 908223 + pending Dear maintainer,
I've prepared an NMU for lxc (versioned as 1:2.0.9-6.2) and uploaded it to DELAYED/5. Please feel free to tell me if I should delay it longer. This is based on the backported patch from Christian Brauner in #908223. https://salsa.debian.org/lxc-team/lxc/merge_requests/1 Regards, Salvatore
diff -Nru lxc-2.0.9/debian/changelog lxc-2.0.9/debian/changelog --- lxc-2.0.9/debian/changelog 2018-08-29 15:22:46.000000000 +0200 +++ lxc-2.0.9/debian/changelog 2018-10-22 21:09:12.000000000 +0200 @@ -1,3 +1,9 @@ +lxc (1:2.0.9-6.2) unstable; urgency=medium + + * autodev: adapt to changes in Linux 4.18 (Closes: #908223) + + -- Salvatore Bonaccorso <car...@debian.org> Mon, 22 Oct 2018 21:09:12 +0200 + lxc (1:2.0.9-6.1) unstable; urgency=medium * Non-maintainer upload. diff -Nru lxc-2.0.9/debian/patches/0007-autodev-adapt-to-changes-in-Linux-4.18.patch lxc-2.0.9/debian/patches/0007-autodev-adapt-to-changes-in-Linux-4.18.patch --- lxc-2.0.9/debian/patches/0007-autodev-adapt-to-changes-in-Linux-4.18.patch 1970-01-01 01:00:00.000000000 +0100 +++ lxc-2.0.9/debian/patches/0007-autodev-adapt-to-changes-in-Linux-4.18.patch 2018-10-22 21:09:12.000000000 +0200 @@ -0,0 +1,219 @@ +From: Christian Brauner <christian.brau...@ubuntu.com> +Date: Mon, 22 Oct 2018 16:30:49 +0200 +Subject: autodev: adapt to changes in Linux 4.18 +Origin: backport, https://github.com/lxc/lxc/commit/db4219603946649474b5cb7915dbd6c17ec728f0 +Bug-Debian: https://bugs.debian.org/908223 + +Starting with commit +55956b59df33 ("vfs: Allow userns root to call mknod on owned filesystems.") +Linux will allow mknod() in user namespaces for userns root if CAP_MKNOD is +available. +However, these device nodes are useless since + +static struct super_block *alloc_super(struct file_system_type *type, int flags, + struct user_namespace *user_ns) +{ + /* <snip> */ + + if (s->s_user_ns != &init_user_ns) + s->s_iflags |= SB_I_NODEV; + + /* <snip> */ +} + +will set the SB_I_NODEV flag on the filesystem. When a device node created in +non-init userns is open()ed the call chain will hit: + +bool may_open_dev(const struct path *path) +{ + return !(path->mnt->mnt_flags & MNT_NODEV) && + !(path->mnt->mnt_sb->s_iflags & SB_I_NODEV); +} + +which will cause an EPERM because the device node is located on an fs +owned by non-init-userns and thus doesn't grant access to device nodes due to +SB_I_NODEV. + +The solution is straightforward. Unless you're real root you should bind-mount +device nodes. + +Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> +--- + src/lxc/conf.c | 127 +++++++++++++++++++++++++++++++------------------ + 1 file changed, 81 insertions(+), 46 deletions(-) + +diff --git a/src/lxc/conf.c b/src/lxc/conf.c +index 91816beb..384138ec 100644 +--- a/src/lxc/conf.c ++++ b/src/lxc/conf.c +@@ -1130,32 +1130,41 @@ 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 }, ++}; ++ ++ ++ ++enum { ++ LXC_DEVNODE_BIND, ++ LXC_DEVNODE_MKNOD, ++ LXC_DEVNODE_PARTIAL, ++ LXC_DEVNODE_OPEN, + }; + + static int lxc_fill_autodev(const struct lxc_rootfs *rootfs) + { +- int ret; +- char path[MAXPATHLEN]; +- int i; ++ int i, ret; ++ char path[PATH_MAX]; + mode_t cmask; ++ int use_mknod = LXC_DEVNODE_MKNOD; + +- ret = snprintf(path, MAXPATHLEN, "%s/dev", ++ ret = snprintf(path, PATH_MAX, "%s/dev", + rootfs->path ? rootfs->mount : ""); +- if (ret < 0 || ret >= MAXPATHLEN) ++ if (ret < 0 || ret >= PATH_MAX) + return -1; + + /* ignore, just don't try to fill in */ +@@ -1165,53 +1174,79 @@ 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[PATH_MAX]; ++ const struct lxc_device_node *device = &lxc_devices[i]; + +- ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", +- rootfs->path ? rootfs->mount : "", d->name); +- if (ret < 0 || ret >= MAXPATHLEN) ++ ret = snprintf(path, PATH_MAX, "%s/dev/%s", ++ rootfs->path ? rootfs->mount : "", device->name); ++ if (ret < 0 || ret >= PATH_MAX) + return -1; + +- ret = mknod(path, d->mode, makedev(d->maj, d->min)); +- if (ret < 0) { +- FILE *pathfile; +- char hostpath[MAXPATHLEN]; ++ if (use_mknod >= LXC_DEVNODE_MKNOD) { ++ ret = mknod(path, device->mode, makedev(device->maj, device->min)); ++ if (ret == 0 || (ret < 0 && errno == EEXIST)) { ++ DEBUG("Created device node \"%s\"", path); ++ } else if (ret < 0) { ++ if (errno != EPERM) { ++ SYSERROR("Failed to create device node \"%s\"", path); ++ return -1; ++ } ++ ++ use_mknod = LXC_DEVNODE_BIND; ++ } + +- if (errno == EEXIST) { +- DEBUG("\"%s\" device already existed", path); ++ /* Device nodes are fully useable. */ ++ if (use_mknod == LXC_DEVNODE_OPEN) + continue; ++ ++ if (use_mknod == LXC_DEVNODE_MKNOD) { ++ /* See ++ * - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=55956b59df336f6738da916dbb520b6e37df9fbd ++ * - https://lists.linuxfoundation.org/pipermail/containers/2018-June/039176.html ++ */ ++ ret = open(path, O_RDONLY | O_CLOEXEC); ++ if (ret >= 0) { ++ close(ret); ++ /* Device nodes are fully useable. */ ++ use_mknod = LXC_DEVNODE_OPEN; ++ continue; ++ } ++ ++ TRACE("Failed to open \"%s\" device", path); ++ /* Device nodes are only partially useable. */ ++ use_mknod = LXC_DEVNODE_PARTIAL; + } ++ } + +- /* Unprivileged containers cannot create devices, so +- * bind mount the device from the host. ++ if (use_mknod != LXC_DEVNODE_PARTIAL) { ++ /* If we are dealing with partially functional device ++ * nodes the prio mknod() call will have created the ++ * device node so we can use it as a bind-mount target. + */ +- ret = snprintf(hostpath, MAXPATHLEN, "/dev/%s", d->name); +- if (ret < 0 || ret >= MAXPATHLEN) +- return -1; +- +- pathfile = fopen(path, "wb"); +- if (!pathfile) { ++ ret = mknod(path, S_IFREG | 0000, 0); ++ if (ret < 0 && errno != EEXIST) { + SYSERROR("Failed to create file \"%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); ++ /* Fallback to bind-mounting the device from the host. */ ++ ret = snprintf(hostpath, PATH_MAX, "/dev/%s", device->name); ++ if (ret < 0 || ret >= PATH_MAX) ++ 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.19.1 + diff -Nru lxc-2.0.9/debian/patches/series lxc-2.0.9/debian/patches/series --- lxc-2.0.9/debian/patches/series 2018-08-29 15:22:46.000000000 +0200 +++ lxc-2.0.9/debian/patches/series 2018-10-22 21:09:12.000000000 +0200 @@ -4,3 +4,4 @@ 0004-debian-Use-iproute2-instead-of-iproute.patch 0005-utils-add-LXC_PROC_PID_FD_LEN_stable-2.0.patch 0006-stable-2.0-lxc-user-nic-verify-file-descriptor.patch +0007-autodev-adapt-to-changes-in-Linux-4.18.patch