[CRIU] [PATCH 03/14] mount: rework perparation for pivot_root (v4)

Andrey Vagin avagin at openvz.org
Wed Oct 15 13:11:52 PDT 2014


We can't bind-mount the required root into itself instead of
resolving a parent mount.

This patch is required to support userns, because if we want to make
pivot_root, the parent mount can't be locked. When we create userns
and mntns, all inherited mounts are marked as locked.

This patch doesn't change properties of the root mount or any other
mounts of the restored namespace. It is needed to satisfy pivot_root().

v2: don't change properties of the given root
v3: bind-mount root into itself recursevly
v4: A parent of the new root may be a shared mount. In a previous
versions a temporary mount is propogated to its neibours.

Cc: Tycho Andersen <tycho.andersen at canonical.com>
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 mount.c | 42 +++++++++++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 13 deletions(-)

diff --git a/mount.c b/mount.c
index d8b6beb..a23bbb8 100644
--- a/mount.c
+++ b/mount.c
@@ -1940,27 +1940,43 @@ int prepare_mnt_ns(void)
 		if (clean_mnt_ns(ns.mnt.mntinfo_tree))
 			return -1;
 	} else {
-		struct mount_info *mi;
-
-		/* moving a mount residing under a shared mount is invalid. */
-		mi = mount_resolve_path(ns.mnt.mntinfo_tree, opts.root);
-		if (mi == NULL) {
-			pr_err("Unable to find mount point for %s\n", opts.root);
+		/*
+		 * A parent of the new root should not be shared, otherwise
+		 * pivot_root() will fail. To achieve this we do:
+		 * 1. copy the new_root mount in a temporary place
+		 * 2. mark the new_root mount as slave
+		 * 3. move the copy of the new_root mount above the new_root mount
+		 *
+		 * A temporary place should not be shared too, because the copy
+		 * of new_mount should not be propagated to somewhere. The old
+		 * root is a good place for that. It will be umounted after
+		 * pivot_root(), so we can change its properties.
+		 */
+		if (mount("none", "/", "none", MS_SLAVE, NULL)) {
+			pr_perror("Can't remount / with MS_SLAVE");
 			return -1;
 		}
-		if (mi->parent == NULL) {
-			pr_err("New root and old root are the same\n");
+		if (mount(opts.root, "/", NULL, MS_BIND | MS_REC, NULL)) {
+			pr_perror("Unable to bind-mount %s to /", opts.root);
 			return -1;
 		}
 
-		/* Our root is mounted over the parent (in the same directory) */
-		if (!strcmp(mi->parent->mountpoint, mi->mountpoint)) {
-			pr_err("The parent of the new root is unreachable\n");
+		if (mount("none", ".", "none", MS_SLAVE, NULL)) {
+			pr_perror("Can't remount the parent of the new root with MS_SLAVE");
 			return -1;
 		}
 
-		if (mount("none", mi->parent->mountpoint + 1, "none", MS_SLAVE, NULL)) {
-			pr_perror("Can't remount the parent of the new root with MS_SLAVE");
+		/*
+		 * "/" is the root for this task. In out case it was overmounted
+		 * and we want to access the upper mount, so we use "/..".
+		 */
+		if (mount("/..", opts.root, NULL, MS_MOVE | MS_REC, NULL)) {
+			pr_perror("Unable to move / to %s", opts.root);
+			return -1;
+		}
+
+		if (chdir(opts.root)) {
+			pr_perror("chdir(%s) failed", opts.root);
 			return -1;
 		}
 	}
-- 
1.9.3



More information about the CRIU mailing list