[lxc-devel] [PATCH 1/1] lxc startup: manually mark every shared mount entry as slave

Serge Hallyn serge.hallyn at ubuntu.com
Wed Apr 16 16:01:22 UTC 2014


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 at ubuntu.com>
---
 src/lxc/conf.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 62 insertions(+), 6 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 06235fb..4052c5f 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);
-- 
1.9.1



More information about the lxc-devel mailing list