]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxc startup: manually mark every shared mount entry as slave
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Wed, 16 Apr 2014 16:01:22 +0000 (11:01 -0500)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Mon, 28 Apr 2014 15:18:47 +0000 (10:18 -0500)
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 <serge.hallyn@ubuntu.com>
src/lxc/conf.c

index 06235fb65365bc866e14659e99ad58be5a2de5b3..4052c5f66b54f5f6020ccb36051b8fb05508300b 100644 (file)
@@ -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);