[v4,34/41] pid: Set pid_ns before we create a child

Submitted by Kirill Tkhai on May 4, 2017, 4:10 p.m.

Details

Message ID 149391425772.11711.2164941603657765799.stgit@localhost.localdomain
State New
Series "Nested pid namespaces support"
Headers show

Commit Message

Kirill Tkhai May 4, 2017, 4:10 p.m.
Get pid_ns of the child and setns() it.
Of course, many optimizations are possible
here, but not for now.

v3: Save current pid_for_children ns to do not do excess setns()
    when it's already set.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/cr-restore.c     |   36 ++++++++++++++++++++++++++++++++++++
 criu/include/pstree.h |    1 +
 2 files changed, 37 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index 72e61188e..c162b59ae 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -419,6 +419,38 @@  static void wait_pid_ns_helper_prepared(struct ns_id *pid_ns, struct pid *pid)
 	futex_wait_while_eq(&pid_ns->pid.helper_created, 0);
 }
 
+static int set_pid_ns_for_children(struct ns_id *pid_ns, struct pid *pid)
+{
+	int fd, ret = 0;
+
+	if (!(root_ns_mask & CLONE_NEWPID))
+		return 0;
+
+	if (last_level_pid(pid) == INIT_PID)
+		return 0;
+
+	BUG_ON(!current);
+
+	if (current->pid_for_children_ns == pid_ns)
+		return 0;
+
+	fd = fdstore_get(pid_ns->pid.nsfd_id);
+	if (fd < 0) {
+		pr_err("Can't get pid_ns fd\n");
+		return -1;
+	}
+
+	if (setns(fd, CLONE_NEWPID) < 0) {
+		pr_perror("Can't set pid ns");
+		ret = -1;
+	} else	{
+		current->pid_for_children_ns = pid_ns;
+	}
+
+	close(fd);
+	return ret;
+}
+
 static rt_sigaction_t sigchld_act;
 /*
  * If parent's sigaction has blocked SIGKILL (which is non-sence),
@@ -1170,6 +1202,7 @@  static inline int fork_with_pid(struct pstree_item *item)
 
 	pid_ns = lookup_ns_by_id(item->ids->pid_ns_id, &pid_ns_desc);
 	BUG_ON(!pid_ns);
+	item->pid_for_children_ns = pid_ns;
 
 	if (item->pid->state != TASK_HELPER) {
 		if (open_core(pid, &ca.core))
@@ -1215,6 +1248,9 @@  static inline int fork_with_pid(struct pstree_item *item)
 
 	wait_pid_ns_helper_prepared(pid_ns, item->pid);
 
+	if (set_pid_ns_for_children(pid_ns, item->pid) < 0)
+		goto err_close;
+
 	if (flock(ca.fd, LOCK_EX)) {
 		pr_perror("%d: Can't lock %s", pid, LAST_PID_PATH);
 		goto err_close;
diff --git a/criu/include/pstree.h b/criu/include/pstree.h
index 9f88983de..8e532066f 100644
--- a/criu/include/pstree.h
+++ b/criu/include/pstree.h
@@ -30,6 +30,7 @@  struct pstree_item {
 		unsigned long	task_st_le_bits;
 	};
 	struct ns_id		*user_ns;
+	struct ns_id		*pid_for_children_ns;
 };
 
 #define vpid(item)	(item->pid->ns[0].virt)