[CRIU] [PATCH 6/6] unshare: Support pidns

Pavel Emelyanov xemul at parallels.com
Wed Dec 9 04:02:46 PST 2015


This one is tricky. When restoring into new pidns we have to provide
some init for it, and root task cannot be such, as it already has non
1 pid.

So for pidns unshare insert a fake entry as root with pid 1 and teach
it to be pseudo-init, i.e. just pick up all died tasks.

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 cr-restore.c       |  7 ++++++-
 crtools.c          |  2 +-
 include/rst_info.h |  5 ++++-
 pstree.c           | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index 74f4b90..deabc5d 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1017,6 +1017,8 @@ static int restore_one_task(int pid, CoreEntry *core)
 		ret = restore_one_zombie(core);
 	else if (current->state == TASK_HELPER) {
 		restore_finish_stage(CR_STATE_RESTORE);
+		if (rsti(current)->helper_cb)
+			rsti(current)->helper_cb();
 		ret = 0;
 	} else {
 		pr_err("Unknown state in code %d\n", (int)core->tc->task_state);
@@ -1121,7 +1123,10 @@ static inline int fork_with_pid(struct pstree_item *item)
 		 * Helper entry will not get moved around and thus
 		 * will live in the parent's cgset.
 		 */
-		rsti(item)->cg_set = rsti(item->parent)->cg_set;
+		if (item->parent)
+			rsti(item)->cg_set = rsti(item->parent)->cg_set;
+		else
+			rsti(item)->cg_set = root_cg_set;
 		ca.core = NULL;
 	}
 
diff --git a/crtools.c b/crtools.c
index 24b4a3f..c82648f 100644
--- a/crtools.c
+++ b/crtools.c
@@ -130,7 +130,7 @@ static int parse_unshare_arg(char *opt)
 	}
 
 	/* Only pid, mnt and user for now */
-	if (opts.unshare_flags & ~(CLONE_NEWNS | 0x1)) {
+	if (opts.unshare_flags & ~(CLONE_NEWNS | CLONE_NEWPID | 0x1)) {
 		pr_err("Unsharing this namespace(s) is not supported yet\n");
 		return -1;
 	}
diff --git a/include/rst_info.h b/include/rst_info.h
index b72e5d0..b6d378e 100644
--- a/include/rst_info.h
+++ b/include/rst_info.h
@@ -65,7 +65,10 @@ struct rst_info {
 	 */
 	bool			has_seccomp;
 
-	void			*breakpoint;
+	union {
+		void		*breakpoint;
+		void		(*helper_cb)(void);
+	};
 };
 
 #endif /* __CR_RST_INFO_H__ */
diff --git a/pstree.c b/pstree.c
index ba547c1..bb30817 100644
--- a/pstree.c
+++ b/pstree.c
@@ -1,6 +1,7 @@
 #include <sys/mman.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <sys/wait.h>
 
 #include "cr_options.h"
 #include "pstree.h"
@@ -11,6 +12,8 @@
 #include "tty.h"
 #include "mount.h"
 #include "asm/dump.h"
+#include "setproctitle.h"
+#include "files.h"
 
 #include "protobuf.h"
 #include "protobuf/pstree.pb-c.h"
@@ -741,9 +744,61 @@ set_mask:
 	return 0;
 }
 
+static void do_fake_init(void)
+{
+	close_old_fds();
+	close_image_dir();
+	close_proc();
+	close_service_fd(CR_PROC_FD_OFF);
+	close_service_fd(ROOT_FD_OFF);
+	close_service_fd(USERNSD_SK);
+	log_fini();
+
+	setproctitle("criu-init");
+
+	while (wait(NULL) >= 0)
+		;
+	exit(0);
+}
+
 static int prepare_pstree_for_unshare(void)
 {
-	{
+	/*
+	 * Unsharing in anything but pid namespace just puts the
+	 * root task into the requesting set. If pidns is the aim,
+	 * then check for the root task to already live in it,
+	 * otherwise -- insert fake init entry into the tree.
+	 */
+
+	if ((opts.unshare_flags & CLONE_NEWPID) &&
+			!(rsti(root_item)->clone_flags & CLONE_NEWPID)) {
+		struct pstree_item *fake_root;
+
+		fake_root = alloc_pstree_item_with_rst();
+
+		fake_root->state = TASK_HELPER;
+		fake_root->pid.virt = INIT_PID;
+		fake_root->pgid = INIT_PID;
+		fake_root->sid = INIT_PID;
+		fake_root->nr_threads = 1;
+		fake_root->threads = xmalloc(sizeof(struct pid));
+		if (!fake_root->threads)
+			return -1;
+
+		fake_root->threads->real = -1;
+		fake_root->threads->virt = INIT_PID;
+		fake_root->ids = root_ids;
+		rsti(fake_root)->clone_flags = opts.unshare_flags | rsti(root_item)->clone_flags;
+
+		rsti(fake_root)->helper_cb = do_fake_init;
+
+		list_add_tail(&root_item->sibling, &fake_root->children);
+		root_item->parent = fake_root;
+		rsti(root_item)->clone_flags = 0;
+
+		task_entries->nr_helpers++;
+		root_item = fake_root;
+	} else {
 		unsigned long aux;
 
 		/*
-- 
1.9.3




More information about the CRIU mailing list