[CRIU] [PATCH 1/4] [v4] mount: open a mount point if it's going to be overmounted

Andrey Vagin avagin at openvz.org
Thu May 12 15:34:54 PDT 2016


From: Andrew Vagin <avagin at virtuozzo.com>

If a mount point has to be bind-mounted to somewhere, we need to have
access to it. This patch solves a problem, when the mount point is
overmounted. In this case we can open the targret mount point and then
use /proc/pid/FD to access it.

v2: make a bind-mount from an underlying mount via a file descriptor
v3: add a separate buffer to generate path to a file descriptor
v4: use the PSFDS contant.

Reported-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
Cc: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
 criu/include/mount.h |  1 +
 criu/mount.c         | 30 ++++++++++++++++++++++++++----
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/criu/include/mount.h b/criu/include/mount.h
index 59e7f9a..c7992ac 100644
--- a/criu/include/mount.h
+++ b/criu/include/mount.h
@@ -49,6 +49,7 @@ struct mount_info {
 	 */
 	char			*mountpoint;
 	char			*ns_mountpoint;
+	int			fd;
 	unsigned		flags;
 	unsigned		sb_flags;
 	int			master_id;
diff --git a/criu/mount.c b/criu/mount.c
index 8e545b1..eb7e234 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -2459,6 +2459,7 @@ static int umount_clean_path()
 
 static int do_bind_mount(struct mount_info *mi)
 {
+	char mnt_fd_path[PSFDS];
 	char *root, *cut_root, rpath[PATH_MAX];
 	unsigned long mflags;
 	int exit_code = -1;
@@ -2499,11 +2500,16 @@ static int do_bind_mount(struct mount_info *mi)
 	 */
 	mi->private = mi->bind->private;
 
-	if (list_empty(&mi->bind->children))
-		mnt_path = mi->bind->mountpoint;
-	else {
+	mnt_path = mi->bind->mountpoint;
+	if (mi->bind->fd >= 0) {
+		snprintf(mnt_fd_path, sizeof(mnt_fd_path),
+					"/proc/self/fd/%d", mi->bind->fd);
+		mnt_path = mnt_fd_path;
+	}
+
+	if (!list_empty(&mi->bind->children)) {
 		/* mi->bind->mountpoint may be overmounted */
-		if (mount(mi->bind->mountpoint, mnt_clean_path, NULL, MS_BIND, NULL)) {
+		if (mount(mnt_path, mnt_clean_path, NULL, MS_BIND, NULL)) {
 			pr_perror("Unable to bind-mount %s to %s",
 					mi->bind->mountpoint, mnt_clean_path);
 		}
@@ -2658,6 +2664,12 @@ static int do_mount_root(struct mount_info *mi)
 	return fetch_rt_stat(mi, mi->mountpoint);
 }
 
+static int do_close_one(struct mount_info *mi)
+{
+	close_safe(&mi->fd);
+	return 0;
+}
+
 static int do_mount_one(struct mount_info *mi)
 {
 	int ret;
@@ -2670,6 +2682,14 @@ static int do_mount_one(struct mount_info *mi)
 		return 1;
 	}
 
+	if (mi->parent && !strcmp(mi->parent->mountpoint, mi->mountpoint)) {
+		mi->parent->fd = open(mi->parent->mountpoint, O_PATH);
+		if (mi->parent->fd < 0) {
+			pr_perror("Unable to open %s", mi->mountpoint);
+			return -1;
+		}
+	}
+
 	pr_debug("\tMounting %s @%s (%d)\n", mi->fstype->name, mi->mountpoint, mi->need_plugin);
 
 	if (!mi->parent) {
@@ -2792,6 +2812,7 @@ struct mount_info *mnt_entry_alloc()
 
 	new = xzalloc(sizeof(struct mount_info));
 	if (new) {
+		new->fd = -1;
 		INIT_LIST_HEAD(&new->children);
 		INIT_LIST_HEAD(&new->siblings);
 		INIT_LIST_HEAD(&new->mnt_slave_list);
@@ -3269,6 +3290,7 @@ static int populate_mnt_ns(void)
 		return -1;
 
 	ret = mnt_tree_for_each(pms, do_mount_one);
+	mnt_tree_for_each(pms, do_close_one);
 
 	if (umount_clean_path())
 		return -1;
-- 
2.7.4



More information about the CRIU mailing list