[v4,38/41] restorer: Set NStids in all pid_ns for thread before we create it.

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

Details

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

Commit Message

Kirill Tkhai May 4, 2017, 4:11 p.m.
If there is multi-level pid, ask helpers to populate /proc last pids
in their active pid namespaces. So, thread will be created with right
NStids.

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 criu/cr-restore.c       |   24 ++++++++++++++++--------
 criu/include/restorer.h |    4 +++-
 criu/pie/restorer.c     |   44 ++++++++++++++++++++++++++++++--------------
 3 files changed, 49 insertions(+), 23 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index b240643f9..7a184b6b1 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -3277,12 +3277,13 @@  static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
 
 	struct vm_area_list self_vmas;
 	struct vm_area_list *vmas = &rsti(current)->vmas;
-	int i, siginfo_n;
+	int i, k, siginfo_n;
 
 	unsigned long creds_pos = 0;
 	unsigned long creds_pos_next;
 
 	sigset_t blockmask;
+	struct ns_id *pid_ns;
 
 	pr_info("Restore via sigreturn\n");
 
@@ -3467,6 +3468,12 @@  static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
 	task_args->sigchld_act	= sigchld_act;
 
 	strncpy(task_args->comm, core->tc->comm, sizeof(task_args->comm));
+	pid_ns = lookup_ns_by_id(current->ids->pid_ns_id, &pid_ns_desc);
+	BUG_ON(!pid_ns);
+	for (i = current->pid->level - 1; i >= 0; i--, pid_ns = pid_ns->parent)
+		task_args->pid_ns_id[i] = pid_ns->id;
+	if (current->pid->level != MAX_NS_NESTING)
+		task_args->pid_ns_id[current->pid->level] = 0; /* Delimiter */
 
 	/*
 	 * Fill up per-thread data.
@@ -3478,14 +3485,15 @@  static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
 		struct rt_sigframe *sigframe;
 		k_rtsigset_t *blkset = NULL;
 
-		thread_args[i].pid = vtid(current, i);
+		for (k = 0; k < current->pid->level; k++)
+			thread_args[i].pid[k] = current->threads[i]->ns[k].virt;
 		thread_args[i].siginfo_n = siginfo_priv_nr[i];
 		thread_args[i].siginfo = task_args->siginfo;
 		thread_args[i].siginfo += siginfo_n;
 		siginfo_n += thread_args[i].siginfo_n;
 
 		/* skip self */
-		if (thread_args[i].pid == pid) {
+		if (thread_args[i].pid[0] == pid) {
 			task_args->t = thread_args + i;
 			tcore = core;
 			blkset = (void *)&tcore->tc->blk_sigset;
@@ -3495,15 +3503,15 @@  static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
 				blkset = (void *)&tcore->thread_core->blk_sigset;
 		}
 
-		if ((tcore->tc || tcore->ids) && thread_args[i].pid != pid) {
+		if ((tcore->tc || tcore->ids) && thread_args[i].pid[0] != pid) {
 			pr_err("Thread has optional fields present %d\n",
-			       thread_args[i].pid);
+			       thread_args[i].pid[0]);
 			ret = -1;
 		}
 
 		if (ret < 0) {
 			pr_err("Can't read core data for thread %d\n",
-			       thread_args[i].pid);
+			       thread_args[i].pid[0]);
 			goto err;
 		}
 
@@ -3533,7 +3541,7 @@  static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
 		if (construct_sigframe(sigframe, sigframe, blkset, tcore))
 			goto err;
 
-		if (thread_args[i].pid != pid)
+		if (thread_args[i].pid[0] != pid)
 			core_entry__free_unpacked(tcore, NULL);
 
 		pr_info("Thread %4d stack %8p rt_sigframe %8p\n",
@@ -3590,7 +3598,7 @@  static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
 		"task_args->nr_threads: %d\n"
 		"task_args->clone_restore_fn: %p\n"
 		"task_args->thread_args: %p\n",
-		task_args, task_args->t->pid,
+		task_args, task_args->t->pid[0],
 		task_args->nr_threads,
 		task_args->clone_restore_fn,
 		task_args->thread_args);
diff --git a/criu/include/restorer.h b/criu/include/restorer.h
index 5b04d1f67..4ece8e45a 100644
--- a/criu/include/restorer.h
+++ b/criu/include/restorer.h
@@ -17,6 +17,7 @@ 
 #include "posix-timer.h"
 #include "timerfd.h"
 #include "shmem.h"
+#include "namespaces.h"
 #include "parasite-vdso.h"
 #include "fault-injection.h"
 
@@ -78,7 +79,7 @@  struct thread_creds_args {
 struct thread_restore_args {
 	struct restore_mem_zone		*mz;
 
-	int				pid;
+	pid_t				pid[MAX_NS_NESTING];
 	UserRegsEntry			gpregs;
 	u64				clear_tid_addr;
 
@@ -167,6 +168,7 @@  struct task_restore_args {
 	auxv_t				mm_saved_auxv[AT_VECTOR_SIZE];
 	u32				mm_saved_auxv_size;
 	char				comm[TASK_COMM_LEN];
+	int				pid_ns_id[MAX_NS_NESTING];
 
 	/*
 	 * proc_fd is a handle to /proc that the restorer blob can use to open
diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
index 6c96a9850..3a8af0b20 100644
--- a/criu/pie/restorer.c
+++ b/criu/pie/restorer.c
@@ -480,10 +480,14 @@  long __export_restore_thread(struct thread_restore_args *args)
 	k_rtsigset_t to_block;
 	unsigned long new_sp;
 	int my_pid = sys_gettid();
-	int ret;
+	int i, ret;
+
+	for (i = 0; i < MAX_NS_NESTING; i++)
+		if (args->pid[i] == 0)
+			break;
 
-	if (my_pid != args->pid) {
-		pr_err("Thread pid mismatch %d/%d\n", my_pid, args->pid);
+	if (my_pid != args->pid[i-1]) {
+		pr_err("Thread pid mismatch %d/%d\n", my_pid, args->pid[i-1]);
 		goto core_restore_end;
 	}
 
@@ -1129,7 +1133,7 @@  static int wait_zombies(struct task_restore_args *task_args)
 long __export_restore_task(struct task_restore_args *args)
 {
 	long ret = -1;
-	int i;
+	int i, k;
 	VmaEntry *vma_entry;
 	unsigned long va;
 
@@ -1433,20 +1437,32 @@  long __export_restore_task(struct task_restore_args *args)
 
 		for (i = 0; i < args->nr_threads; i++) {
 			char last_pid_buf[16], *s;
-
 			/* skip self */
-			if (thread_args[i].pid == args->t->pid)
+			if (thread_args[i].pid[0] == args->t->pid[0])
 				continue;
 
-			new_sp = restorer_stack(thread_args[i].mz);
-			last_pid_len = std_vprint_num(last_pid_buf, sizeof(last_pid_buf), thread_args[i].pid - 1, &s);
-			sys_lseek(fd, 0, SEEK_SET);
-			ret = sys_write(fd, s, last_pid_len);
-			if (ret < 0) {
-				pr_err("Can't set last_pid %ld/%s\n", ret, last_pid_buf);
-				sys_close(fd);
-				goto core_restore_end;
+			if (thread_args[i].pid[1] == 0) {
+				/* One level pid ns hierarhy */
+				last_pid_len = std_vprint_num(last_pid_buf, sizeof(last_pid_buf), thread_args[i].pid[0] - 1, &s);
+				sys_lseek(fd, 0, SEEK_SET);
+				ret = sys_write(fd, s, last_pid_len);
+				if (ret < 0) {
+					pr_err("Can't set last_pid %ld/%s\n", ret, last_pid_buf);
+					sys_close(fd);
+					goto core_restore_end;
+				}
+			} else {
+				for (k = 0; k < MAX_NS_NESTING; k++) {
+					if (thread_args[i].pid[k] == 0)
+						break;
+					if (request_set_next_pid(args->pid_ns_id[k], thread_args[i].pid[k], args->transport_fd) < 0) {
+						pr_err("Can't request to set pid\n");
+						sys_close(fd);
+						goto core_restore_end;
+					}
+				}
 			}
+			new_sp = restorer_stack(thread_args[i].mz);
 
 			/*
 			 * To achieve functionality like libc's clone()