Blob Blame History Raw
From 573137b58e00dce2d58c7e669a6a07ecbcddf9b0 Mon Sep 17 00:00:00 2001
From: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Date: Fri, 26 Nov 2021 12:53:41 +0300
Subject: [PATCH 170/245] mount: restrict mp-external mount map to init
 container mntns only

We resolve mountpoint-external mounts on dump by mountpoint comparison,
so if we have other mount (other superblock e.g. in nested mntns) with
same mountpoint we would also resolve this mount as external and restore
it as external: replacing it completely with different mount... That's
wrong, so to make this interface more robust let's only resolve
mountpoint-external mounts in root mntns of container, not in all
mntnses as it was before.

Note: if actual external mount (bind of external) gets to nested mntns
it's ok not to resolve it as external as criu would bind it from the
resolved mount in root mntns. So external mounts in nested mntns are
still supported after this patch.

Cherry-picked one hunk from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/034498b28

Changes: apply mntns check only to mountpoint-external mounts.

Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
---
 criu/mount.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/criu/mount.c b/criu/mount.c
index 968b6dc03..ff9b9b591 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -470,14 +470,23 @@ static void mnt_tree_show(struct mount_info *tree, int off)
 /* Returns -1 on error, 1 if external mount resolved, 0 otherwise */
 static int try_resolve_ext_mount(struct mount_info *info)
 {
-	char *ext;
 	char devstr[64];
 
-	ext = ext_mount_lookup(info->mountpoint + 1 /* trim the . */);
-	if (ext) {
-		pr_info("Found %s mapping for %s mountpoint\n", ext, info->mountpoint);
-		info->external = ext;
-		return 1;
+	/*
+	 * Only allow mountpoint-external mounts in root mntns. Their lookup is
+	 * based on mountpoint path, but in nested mntns we can have completely
+	 * different mount tree and at same mountpoint we can have completely
+	 * different mount.
+	 */
+	if (info->nsid->type == NS_ROOT) {
+		char *ext;
+
+		ext = ext_mount_lookup(info->mountpoint + 1 /* trim the . */);
+		if (ext) {
+			pr_info("Found %s mapping for %s mountpoint\n", ext, info->mountpoint);
+			info->external = ext;
+			return 1;
+		}
 	}
 
 	snprintf(devstr, sizeof(devstr), "dev[%d/%d]", kdev_major(info->s_dev), kdev_minor(info->s_dev));
-- 
2.35.1