[CRIU] [PATCH 12/14] zdtm: prepare a file tree for userns

Andrey Vagin avagin at openvz.org
Tue Oct 14 04:38:26 PDT 2014


Here are two issues:
1. All mounts in a new user namespace are locked, so
we need to create a new root mount. We need to bind-mount root to
itself.
2. /proc and /sys must be mounted before umounting /proc and /sys
which were inhereted. It's a security policy.

"""
Author: Eric W. Biederman <ebiederm at xmission.com>
Date:   Sun Mar 24 14:28:27 2013 -0700

    userns: Restrict when proc and sysfs can be mounted

    Only allow unprivileged mounts of proc and sysfs if they are already
    mounted when the user namespace is created.
"""

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 test/zdtm/lib/ns.c | 48 +++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 37 insertions(+), 11 deletions(-)

diff --git a/test/zdtm/lib/ns.c b/test/zdtm/lib/ns.c
index a7e3261..9901f5f 100644
--- a/test/zdtm/lib/ns.c
+++ b/test/zdtm/lib/ns.c
@@ -19,8 +19,9 @@
 extern int pivot_root(const char *new_root, const char *put_old);
 static int prepare_mntns()
 {
-	int dfd;
+	int dfd, ret;
 	char *root;
+	char path[PATH_MAX];
 
 	root = getenv("ZDTM_ROOT");
 	if (!root) {
@@ -28,7 +29,28 @@ static int prepare_mntns()
 		return -1;
 	}
 
-		dfd = open(".", O_RDONLY);
+		/*
+		 * In a new userns all mounts are locked to protect what is
+		 * under them. So we need to create another mount for the
+		 * new root.
+		 */
+		if (mount("/", "/", NULL, MS_PRIVATE | MS_REC, NULL)) {
+			fprintf(stderr, "Can't bind-mount root: %m\n");
+			return -1;
+		}
+
+		if (mount(root, root, NULL, MS_BIND | MS_REC, NULL)) {
+			fprintf(stderr, "Can't bind-mount root: %m\n");
+			return -1;
+		}
+
+		/* Move current working directory to the new root */
+		ret = readlink("/proc/self/cwd", path, sizeof(path) - 1);
+		if (ret < 0)
+			return -1;
+		path[ret] = 0;
+
+		dfd = open(path, O_RDONLY | O_DIRECTORY);
 		if (dfd == -1) {
 			fprintf(stderr, "open(.) failed: %m\n");
 			return -1;
@@ -43,27 +65,31 @@ static int prepare_mntns()
 			return -1;
 		}
 
-		if (mount("none", "/", "none", MS_REC|MS_PRIVATE, NULL)) {
-			fprintf(stderr, "Can't remount root with MS_PRIVATE: %m\n");
-			return -1;
-		}
-
 		if (pivot_root(".", "./old")) {
 			fprintf(stderr, "pivot_root(., ./old) failed: %m\n");
 			return -1;
 		}
-		if (umount2("./old", MNT_DETACH)) {
-			fprintf(stderr, "umount(./old) failed: %m\n");
-			return -1;
-		}
+
 		if (mkdir("proc", 0777) && errno != EEXIST) {
 			fprintf(stderr, "mkdir(proc) failed: %m\n");
 			return -1;
 		}
+
+		/*
+		 * proc and sysfs can be mounted in an unprivileged namespace,
+		 * if they are already mounted when the user namespace is created.
+		 * So ./old must be umounted after mounting /proc and /sys.
+		 */
 		if (mount("proc", "/proc", "proc", MS_MGC_VAL, NULL)) {
 			fprintf(stderr, "mount(/proc) failed: %m\n");
 			return -1;
 		}
+
+		if (umount2("./old", MNT_DETACH)) {
+			fprintf(stderr, "umount(./old) failed: %m\n");
+			return -1;
+		}
+
 		if (mkdir("/dev", 0755) && errno != EEXIST) {
 			fprintf(stderr, "mkdir(/dev) failed: %m\n");
 			return -1;
-- 
1.9.3



More information about the CRIU mailing list