From: Serge Hallyn Date: Wed, 16 Apr 2014 16:01:22 +0000 (-0500) Subject: lxc startup: manually mark every shared mount entry as slave X-Git-Tag: lxc-1.1.0.alpha1~144 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e995d7a269b3f158055e94a5f043211cd81a6966;p=thirdparty%2Flxc.git lxc startup: manually mark every shared mount entry as slave If you 'ip netns add x1', this creates /run/netns and /run/netns/x1 as shared mounts. When a container starts, it umounts these after pivot_root, and the umount is propagated to the host. Worse, doing mount("", "/", NULL, MS_SLAVE|MS_REC, NULL) does not suffice to change those, even after binding /proc/mounts onto /etc/mtab. So, I give up. Do this manually, walking over /proc/self/mountinfo and changing the mount propagation on everything marked as shared. With this patch, lxc-start no longer unmounts /run/netns/* on the host. Signed-off-by: Serge Hallyn --- diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 06235fb65..4052c5f66 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -3706,6 +3706,66 @@ void tmp_proc_unmount(struct lxc_conf *lxc_conf) } } +static void null_endofword(char *word) +{ + while (*word && *word != ' ' && *word != '\t') + word++; + *word = '\0'; +} + +/* + * skip @nfields spaces in @src + */ +static char *get_field(char *src, int nfields) +{ + char *p = src; + int i; + + for (i = 0; i < nfields; i++) { + while (*p && *p != ' ' && *p != '\t') + p++; + if (!p) + break; + p++; + } + return p; +} + +static void remount_all_slave(void) +{ + /* walk /proc/mounts and change any shared entries to slave */ + FILE *f = fopen("/proc/self/mountinfo", "r"); + char *line = NULL; + size_t len = 0; + + if (!f) { + SYSERROR("Failed to open /proc/self/mountinfo to mark all shared"); + ERROR("Continuing container startup..."); + return; + } + + while (getline(&line, &len, f) != -1) { + char *target, *opts; + target = get_field(line, 4); + if (!target) + continue; + opts = get_field(target, 2); + if (!opts) + continue; + null_endofword(opts); + if (!strstr(opts, "shared")) + continue; + null_endofword(target); + if (mount(NULL, target, NULL, MS_SLAVE, NULL)) { + SYSERROR("Failed to make %s rslave", target); + ERROR("Continuing..."); + } + } + fclose(f); + if (line) + free(line); +} + int lxc_setup(struct lxc_handler *handler) { const char *name = handler->name; @@ -3713,12 +3773,6 @@ int lxc_setup(struct lxc_handler *handler) const char *lxcpath = handler->lxcpath; void *data = handler->data; - if (detect_shared_rootfs()) { - if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) { - SYSERROR("Failed to make / rslave"); - ERROR("Continuing..."); - } - } if (detect_ramfs_rootfs()) { if (chroot_into_slave(lxc_conf)) { ERROR("Failed to chroot into slave /"); @@ -3726,6 +3780,8 @@ int lxc_setup(struct lxc_handler *handler) } } + remount_all_slave(); + if (lxc_conf->inherit_ns_fd[LXC_NS_UTS] == -1) { if (setup_utsname(lxc_conf->utsname)) { ERROR("failed to setup the utsname for '%s'", name);