[CRIU] [PATCH 3/5] mount: create a slave pty if it has to be bind-mounted to somewhere

Andrei Vagin avagin at openvz.org
Tue Feb 7 00:43:29 PST 2017


From: Andrei Vagin <avagin at virtuozzo.com>

Now we create pty pairs when file descriptors are restored.
The problem is that a slave tty can be bind-mounted to somewhere
and in this case we have to create this pair and hold a master file
descritore before related file descriptors will not be restored.

In this patch, a unix socket is used to hold file descriptros.
And we use SK_PEEK_OFF and MSG_PEEK to get any of them.

Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
 criu/cr-restore.c  | 29 ++++++++++++++++----
 criu/filesystems.c |  2 ++
 criu/include/tty.h |  3 ++
 criu/tty.c         | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 108 insertions(+), 6 deletions(-)

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 9fa9bc3..911d7af 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -77,6 +77,7 @@
 #include "fault-injection.h"
 #include "sk-queue.h"
 #include "sigframe.h"
+#include "fdstore.h"
 
 #include "parasite-syscall.h"
 #include "files-reg.h"
@@ -174,9 +175,6 @@ static struct collect_image_info *cinfos[] = {
 	&inotify_mark_cinfo,
 	&fanotify_cinfo,
 	&fanotify_mark_cinfo,
-	&tty_info_cinfo,
-	&tty_cinfo,
-	&tty_cdata,
 	&tunfile_cinfo,
 	&ext_file_cinfo,
 	&timerfd_cinfo,
@@ -186,6 +184,13 @@ static struct collect_image_info *cinfos[] = {
 	&sk_queues_cinfo,
 };
 
+/* These images are requered to restore namespaces */
+static struct collect_image_info *before_ns_cinfos[] = {
+	&tty_info_cinfo, /* Restore devpts content */
+	&tty_cinfo,
+	&tty_cdata,
+};
+
 struct post_prepare_cb {
 	struct list_head list;
 	int (*actor)(void *data);
@@ -226,9 +231,6 @@ static int root_prepare_shared(void)
 
 	pr_info("Preparing info about shared resources\n");
 
-	if (prepare_shared_tty())
-		return -1;
-
 	if (prepare_shared_reg_files())
 		return -1;
 
@@ -1399,6 +1401,13 @@ static int restore_task_with_children(void *_arg)
 
 	/* Restore root task */
 	if (current->parent == NULL) {
+		int i;
+
+		if (prepare_shared_tty())
+			goto err;
+
+		if (fdstore_init())
+			goto err;
 		if (join_namespaces()) {
 			pr_perror("Join namespaces failed");
 			goto err;
@@ -1415,6 +1424,13 @@ static int restore_task_with_children(void *_arg)
 		if (mount_proc())
 			goto err;
 
+		for (i = 0; i < ARRAY_SIZE(before_ns_cinfos); i++) {
+			ret = collect_image(before_ns_cinfos[i]);
+			if (ret)
+				return -1;
+		}
+
+
 		if (prepare_namespace(current, ca->clone_flags))
 			goto err;
 
@@ -3197,6 +3213,7 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
 	close_proc();
 	close_service_fd(ROOT_FD_OFF);
 	close_service_fd(USERNSD_SK);
+	close_service_fd(FDSTORE_SK_OFF);
 	close_service_fd(RPC_SK_OFF);
 
 	__gcov_flush();
diff --git a/criu/filesystems.c b/criu/filesystems.c
index 7fc4c26..4688d1f 100644
--- a/criu/filesystems.c
+++ b/criu/filesystems.c
@@ -18,6 +18,7 @@
 #include "autofs.h"
 #include "util.h"
 #include "fs-magic.h"
+#include "tty.h"
 
 #include "images/mnt.pb-c.h"
 #include "images/binfmt-misc.pb-c.h"
@@ -698,6 +699,7 @@ static struct fstype fstypes[] = {
 		.name = "devpts",
 		.parse = devpts_parse,
 		.code = FSTYPE__DEVPTS,
+		.restore = devpts_restore,
 	}, {
 		.name = "simfs",
 		.code = FSTYPE__SIMFS,
diff --git a/criu/include/tty.h b/criu/include/tty.h
index 6fa00db..4656038 100644
--- a/criu/include/tty.h
+++ b/criu/include/tty.h
@@ -29,6 +29,9 @@ extern struct collect_image_info tty_cinfo;
 extern struct collect_image_info tty_cdata;
 extern int prepare_shared_tty(void);
 
+struct mount_info;
+extern int devpts_restore(struct mount_info *pm);
+
 extern int tty_prep_fds(void);
 extern void tty_fini_fds(void);
 
diff --git a/criu/tty.c b/criu/tty.c
index 5bfce44..c1bb95c 100644
--- a/criu/tty.c
+++ b/criu/tty.c
@@ -29,6 +29,7 @@
 #include "namespaces.h"
 #include "external.h"
 #include "action-scripts.h"
+#include "mount.h"
 
 #include "protobuf.h"
 #include "util.h"
@@ -38,6 +39,7 @@
 #include "parasite.h"
 
 #include "pstree.h"
+#include "fdstore.h"
 #include "tty.h"
 
 /*
@@ -102,6 +104,8 @@ struct tty_info {
 	struct tty_info			*ctl_tty;
 	struct tty_info			*link;
 	struct tty_data_entry		*tty_data;
+
+	int				fdstore_id;
 };
 
 struct tty_dump_info {
@@ -616,6 +620,9 @@ static int __pty_open_ptmx_index(int index, int flags,
 
 static int pty_open_ptmx_index(struct file_desc *d, struct tty_info *info, int flags)
 {
+	if (info->fdstore_id >= 0)
+		return fdstore_get(info->fdstore_id);
+
 	return __pty_open_ptmx_index(info->tie->pty->index, flags,
 					open_tty_reg, d, path_from_reg(d));
 }
@@ -1632,6 +1639,7 @@ static int collect_one_tty(void *obj, ProtobufCMessage *msg, struct cr_img *i)
 			return -1;
 	}
 
+	info->fdstore_id = -1;
 	list_add(&info->list, &all_ttys);
 	return file_desc_add(&info->d, info->tfe->id, &tty_desc_ops);
 }
@@ -2143,3 +2151,75 @@ void tty_fini_fds(void)
 {
 	close_service_fd(SELF_STDIN_OFF);
 }
+
+static int open_pty(void *arg, int flags)
+{
+	int dfd = (unsigned long) arg;
+	/*
+	 * Never set as a control terminal automatically, all
+	 * ctty magic happens only in tty_set_sid().
+	 */
+	flags |= O_NOCTTY;
+	return openat(dfd, "ptmx", flags);
+}
+
+/* Create a pty pair and save a master descriptor in fdstore */
+static int pty_create_ptmx_index(int dfd, int index, int flags)
+{
+	struct tty_info *info;
+	int fd, id;
+
+	fd = __pty_open_ptmx_index(index, flags, open_pty, (void *)(unsigned long) dfd, "ptmx");
+	if (fd < 0)
+		return -1;
+
+	id = fdstore_add(fd);
+	if (id < 0)
+		return -1;
+	close(fd);
+
+	list_for_each_entry(info, &all_ttys, list) {
+		if (!is_pty(info->driver))
+			continue;
+
+		if (info->tie->pty->index == index) {
+			info->fdstore_id = id;
+		}
+	}
+
+	return 0;
+}
+
+/* Restore slave pty-s which have to be bind-mounted to somewhere */
+int devpts_restore(struct mount_info *pm)
+{
+	struct mount_info *bm;
+	int dfd, exit_code = -1;
+
+	dfd = open(pm->mountpoint, O_RDONLY);
+	if (dfd < 0) {
+		pr_perror("Unable to open %s", pm->mountpoint);
+		return -1;
+	}
+
+
+	list_for_each_entry(bm, &pm->mnt_bind, mnt_bind) {
+		int idx;
+		struct stat st;
+
+		if (sscanf(bm->root, "/%d", &idx) < 1)
+			continue;
+
+		if (fstatat(dfd, bm->root + 1, &st, 0) == 0)
+			continue;
+
+		pr_debug("Create a slave tty %d\n", idx);
+		if (pty_create_ptmx_index(dfd, idx, O_RDWR))
+			goto err;
+	}
+
+	exit_code = 0;
+err:
+	close(dfd);
+	return exit_code;
+}
-- 
2.7.4



More information about the CRIU mailing list