[CRIU] [PATCH 2/2] tty: check that a master of a bind-mounted slave is in the root mntns

Andrei Vagin avagin at openvz.org
Tue Feb 21 22:39:46 PST 2017


From: Andrei Vagin <avagin at virtuozzo.com>

Here we check that a master of a bind-mounted slave was opened in the
root mount namespace. The problem is that we restore all mounts in the
root mount namespace. Only when all mounts are restored, we create other
mount namespaces.  So when we are restoring mounts, we can open files
only in the root mount namespace.

Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
 criu/filesystems.c         |  1 +
 criu/include/filesystems.h |  1 +
 criu/include/tty.h         |  2 ++
 criu/mount.c               |  4 ++++
 criu/tty.c                 | 59 ++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 67 insertions(+)

diff --git a/criu/filesystems.c b/criu/filesystems.c
index 4688d1f..1ab8599 100644
--- a/criu/filesystems.c
+++ b/criu/filesystems.c
@@ -700,6 +700,7 @@ static struct fstype fstypes[] = {
 		.parse = devpts_parse,
 		.code = FSTYPE__DEVPTS,
 		.restore = devpts_restore,
+		.dump_bindmount = devpts_dump_bindmount,
 	}, {
 		.name = "simfs",
 		.code = FSTYPE__SIMFS,
diff --git a/criu/include/filesystems.h b/criu/include/filesystems.h
index 5aea32d..be270fa 100644
--- a/criu/include/filesystems.h
+++ b/criu/include/filesystems.h
@@ -13,6 +13,7 @@ struct fstype {
 	int code;
 	int (*dump)(struct mount_info *pm);
 	int (*restore)(struct mount_info *pm);
+	int (*dump_bindmount)(struct mount_info *pm);
 	int (*parse)(struct mount_info *pm);
 	int (*collect)(struct mount_info *pm);
 	bool (*sb_equal)(struct mount_info *a, struct mount_info *b);
diff --git a/criu/include/tty.h b/criu/include/tty.h
index 4656038..54bc142 100644
--- a/criu/include/tty.h
+++ b/criu/include/tty.h
@@ -37,6 +37,8 @@ extern void tty_fini_fds(void);
 
 extern int tty_restore_ctl_terminal(struct file_desc *d, int fd);
 
+extern int devpts_dump_bindmount(struct mount_info *m);
+
 #define OPT_SHELL_JOB	"shell-job"
 
 #endif /* __CR_TTY_H__ */
diff --git a/criu/mount.c b/criu/mount.c
index 5520b23..531cb3e 100644
--- a/criu/mount.c
+++ b/criu/mount.c
@@ -1267,6 +1267,10 @@ static int dump_one_mountpoint(struct mount_info *pm, struct cr_img *img)
 	if (!pm->dumped && dump_one_fs(pm))
 		return -1;
 
+	if (!fsroot_mounted(pm) &&
+	    pm->fstype->dump_bindmount && pm->fstype->dump_bindmount(pm))
+		return -1;
+
 	if (pm->mnt_id == CRTIME_MNT_ID) {
 		pr_info("Skip dumping cr-time mountpoint: %s\n", pm->mountpoint);
 		return 0;
diff --git a/criu/tty.c b/criu/tty.c
index bd861e9..62da7a1 100644
--- a/criu/tty.c
+++ b/criu/tty.c
@@ -115,6 +115,7 @@ struct tty_dump_info {
 	pid_t				sid;
 	pid_t				pgrp;
 	int				fd;
+	int				mnt_id;
 	struct tty_driver		*driver;
 
 	int				index;
@@ -1755,6 +1756,7 @@ static int dump_tty_info(int lfd, u32 id, const struct fd_parms *p, struct tty_d
 	dinfo->sid		= pti->sid;
 	dinfo->pgrp		= pti->pgrp;
 	dinfo->fd		= p->fd;
+	dinfo->mnt_id		= p->mnt_id;
 	dinfo->driver		= driver;
 	dinfo->flags		= p->flags;
 
@@ -2182,6 +2184,63 @@ static int pty_create_ptmx_index(int dfd, int index, int flags)
 	return 0;
 }
 
+/*
+ * Here we check that a master of a bind-mounted slave was opened in the root
+ * mount namespace. The problem is that we restore all mounts in the root mount
+ * namespace. Only when all mounts are restored, we create other mount
+ * namespaces. So when we are restoring mounts, we can open files only in the
+ * root mount namespace.
+ */
+int devpts_dump_bindmount(struct mount_info *m)
+{
+	struct tty_dump_info *dinfo = NULL;
+	struct mount_info *master_mp;
+	int index;
+
+	if (strcmp(m->root, "/") == 0 || strcmp(m->root, "/ptmx") == 0)
+		return 0;
+
+	if (sscanf(m->root, "/%d", &index) != 1) {
+		pr_err("Unable to parse %s", m->root);
+		return -1;
+	}
+
+	list_for_each_entry(dinfo, &all_ttys, list) {
+		if (!is_pty(dinfo->driver))
+			continue;
+
+		if (dinfo->driver->subtype != TTY_SUBTYPE_MASTER)
+			continue;
+
+		if (dinfo->index == index)
+			goto found;
+	}
+
+	if (opts.orphan_pts_master) /* external master */
+		return 0;
+
+	pr_err("Unable to find a master for %s\n", m->root);
+	return -1;
+
+found:
+	/* mnt_id isn't reported in fdinfo, so here is only one mntns */
+	if (dinfo->mnt_id == -1)
+		return 0;
+
+	master_mp = lookup_mnt_id(dinfo->mnt_id);
+	if (!master_mp) {
+		pr_err("Unable to find a mount %d\n", dinfo->mnt_id);
+		return -1;
+	}
+
+	if (master_mp->nsid->type != NS_ROOT) {
+		pr_err("The master for %s isn't from the root mntns", m->root);
+		return -1;
+	}
+
+	return 0;
+}
+
 /* Restore slave pty-s which have to be bind-mounted to somewhere */
 int devpts_restore(struct mount_info *pm)
 {
-- 
2.7.4



More information about the CRIU mailing list