[lxc-devel] [PATCH 1/1] always check whether rootfs is shared

Serge Hallyn serge.hallyn at ubuntu.com
Tue Feb 25 05:08:26 UTC 2014


(this expands on Dwight's recent patch, commit c597baa8f9)

After unshare(CLONE_NEWNS) and before doing any mounting, always
check whether rootfs is shared.  Otherwise template runs or clone
scripts can bleed mount activity to the host.

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 src/lxc/attach.c         |  7 +++++++
 src/lxc/bdev.c           |  7 +++++++
 src/lxc/conf.c           | 40 ----------------------------------------
 src/lxc/lxc_usernsexec.c |  7 +++++++
 src/lxc/lxccontainer.c   |  6 ++++++
 src/lxc/utils.c          | 40 ++++++++++++++++++++++++++++++++++++++++
 src/lxc/utils.h          |  2 ++
 7 files changed, 69 insertions(+), 40 deletions(-)

diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index f12d216..9136ec2 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -220,6 +220,13 @@ static int lxc_attach_remount_sys_proc(void)
 		return -1;
 	}
 
+	if (detect_shared_rootfs()) {
+		if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
+			SYSERROR("Failed to make / rslave to run rsync");
+			ERROR("Continuing...");
+		}
+	}
+
 	/* assume /proc is always mounted, so remount it */
 	ret = umount2("/proc", MNT_DETACH);
 	if (ret < 0) {
diff --git a/src/lxc/bdev.c b/src/lxc/bdev.c
index 952cfeb..40f70c5 100644
--- a/src/lxc/bdev.c
+++ b/src/lxc/bdev.c
@@ -302,6 +302,13 @@ static int detect_fs(struct bdev *bdev, char *type, int len)
 	if (unshare(CLONE_NEWNS) < 0)
 		exit(1);
 
+	if (detect_shared_rootfs()) {
+		if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
+			SYSERROR("Failed to make / rslave to run rsync");
+			ERROR("Continuing...");
+		}
+	}
+
 	ret = mount_unknown_fs(srcdev, bdev->dest, bdev->mntopts);
 	if (ret < 0) {
 		ERROR("failed mounting %s onto %s to detect fstype", srcdev, bdev->dest);
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index c9dd7ac..fc39897 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1427,46 +1427,6 @@ static int setup_autodev(const char *root)
 }
 
 /*
- * Detect whether / is mounted MS_SHARED.  The only way I know of to
- * check that is through /proc/self/mountinfo.
- * I'm only checking for /.  If the container rootfs or mount location
- * is MS_SHARED, but not '/', then you're out of luck - figuring that
- * out would be too much work to be worth it.
- */
-#define LINELEN 4096
-int detect_shared_rootfs(void)
-{
-	char buf[LINELEN], *p;
-	FILE *f;
-	int i;
-	char *p2;
-
-	f = fopen("/proc/self/mountinfo", "r");
-	if (!f)
-		return 0;
-	while (fgets(buf, LINELEN, f)) {
-		for (p = buf, i=0; p && i < 4; i++)
-			p = index(p+1, ' ');
-		if (!p)
-			continue;
-		p2 = index(p+1, ' ');
-		if (!p2)
-			continue;
-		*p2 = '\0';
-		if (strcmp(p+1, "/") == 0) {
-			// this is '/'.  is it shared?
-			p = index(p2+1, ' ');
-			if (p && strstr(p, "shared:")) {
-				fclose(f);
-				return 1;
-			}
-		}
-	}
-	fclose(f);
-	return 0;
-}
-
-/*
  * I'll forgive you for asking whether all of this is needed :)  The
  * answer is yes.
  * pivot_root will fail if the new root, the put_old dir, or the parent
diff --git a/src/lxc/lxc_usernsexec.c b/src/lxc/lxc_usernsexec.c
index e40fa53..6784633 100644
--- a/src/lxc/lxc_usernsexec.c
+++ b/src/lxc/lxc_usernsexec.c
@@ -35,6 +35,7 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/mount.h>
 #include <sys/wait.h>
 #include <sched.h>
 #include <pwd.h>
@@ -111,6 +112,12 @@ static int do_child(void *vargv)
 		perror("unshare CLONE_NEWNS");
 		return -1;
 	}
+	if (detect_shared_rootfs()) {
+		if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
+			printf("Failed to make / rslave to run rsync");
+			return -1;
+		}
+	}
 	execvp(argv[0], argv);
 	perror("execvpe");
 	return -1;
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 0d89d11..8eb2d8b 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -2502,6 +2502,12 @@ static int clone_update_rootfs(struct clone_update_data *data)
 			bdev_put(bdev);
 			return -1;
 		}
+		if (detect_shared_rootfs()) {
+			if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL)) {
+				SYSERROR("Failed to make / rslave to run rsync");
+				ERROR("Continuing...");
+			}
+		}
 		if (bdev->ops->mount(bdev) < 0) {
 			bdev_put(bdev);
 			return -1;
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 52e4c86..da7c3b4 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1194,3 +1194,43 @@ uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
 
 	return hval;
 }
+
+/*
+ * Detect whether / is mounted MS_SHARED.  The only way I know of to
+ * check that is through /proc/self/mountinfo.
+ * I'm only checking for /.  If the container rootfs or mount location
+ * is MS_SHARED, but not '/', then you're out of luck - figuring that
+ * out would be too much work to be worth it.
+ */
+#define LINELEN 4096
+int detect_shared_rootfs(void)
+{
+	char buf[LINELEN], *p;
+	FILE *f;
+	int i;
+	char *p2;
+
+	f = fopen("/proc/self/mountinfo", "r");
+	if (!f)
+		return 0;
+	while (fgets(buf, LINELEN, f)) {
+		for (p = buf, i=0; p && i < 4; i++)
+			p = index(p+1, ' ');
+		if (!p)
+			continue;
+		p2 = index(p+1, ' ');
+		if (!p2)
+			continue;
+		*p2 = '\0';
+		if (strcmp(p+1, "/") == 0) {
+			// this is '/'.  is it shared?
+			p = index(p2+1, ' ');
+			if (p && strstr(p, "shared:")) {
+				fclose(f);
+				return 1;
+			}
+		}
+	}
+	fclose(f);
+	return 0;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index f6f3373..dcf0e34 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -276,3 +276,5 @@ extern bool dir_exists(const char *path);
 #define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL)
 uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval);
 #endif
+
+int detect_shared_rootfs(void);
-- 
1.9.0



More information about the lxc-devel mailing list