[CRIU] [PATCH 20/21] ns: Restore pid_for_children ns in threads
Kirill Tkhai
ktkhai at virtuozzo.com
Tue May 23 05:41:26 PDT 2017
Threads may have different pid_for_children ns.
Allow them to set it after they are created:
just get a pid_ns fd from fdstore, and setns()
to it, after thread creation.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/cr-restore.c | 24 ++++++++++++++++++++++++
criu/include/restorer.h | 1 +
criu/pie/restorer.c | 33 ++++++++++++++++++++++++++++-----
3 files changed, 53 insertions(+), 5 deletions(-)
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index b3d686f3f..17bd9c2d2 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -3035,6 +3035,25 @@ static int prepare_signals(int pid, struct task_restore_args *ta, CoreEntry *lea
return ret;
}
+static int get_thread_pid_ns_fd(uint32_t pid_ns_id)
+{
+ struct ns_id *ns;
+ int fd;
+
+ if (current->pid_for_children_ns->id == pid_ns_id)
+ return -2;
+
+ ns = lookup_ns_by_id(pid_ns_id, &pid_ns_desc);
+ BUG_ON(!ns);
+
+ fd = fdstore_get(ns->pid.nsfd_id);
+ if (fd < 0) {
+ pr_err("Can't get pid_ns fd\n");
+ return -1;
+ }
+ return fd;
+}
+
extern void __gcov_flush(void) __attribute__((weak));
void __gcov_flush(void) {}
@@ -3509,12 +3528,17 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
task_args->t = thread_args + i;
tcore = core;
blkset = (void *)&tcore->tc->blk_sigset;
+ thread_args[i].pfc_ns_fd = get_thread_pid_ns_fd(current->ids->pid_for_children_ns_id);
} else {
tcore = current->core[i];
if (tcore->thread_core->has_blk_sigset)
blkset = (void *)&tcore->thread_core->blk_sigset;
+ thread_args[i].pfc_ns_fd = get_thread_pid_ns_fd(tcore->ids->pid_for_children_ns_id);
}
+ if (thread_args[i].pfc_ns_fd == -1)
+ goto err;
+
if ((tcore->tc) && thread_args[i].pid[0] != pid) {
pr_err("Thread has optional fields present %d\n",
thread_args[i].pid[0]);
diff --git a/criu/include/restorer.h b/criu/include/restorer.h
index 1866bbd82..736ba96a9 100644
--- a/criu/include/restorer.h
+++ b/criu/include/restorer.h
@@ -96,6 +96,7 @@ struct thread_restore_args {
unsigned int siginfo_n;
int pdeath_sig;
+ int pfc_ns_fd;
struct thread_creds_args *creds_args;
} __aligned(64);
diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
index 736c12504..f6c30d180 100644
--- a/criu/pie/restorer.c
+++ b/criu/pie/restorer.c
@@ -500,7 +500,7 @@ long __export_restore_thread(struct thread_restore_args *args)
k_rtsigset_t to_block;
unsigned long new_sp;
int my_pid = sys_gettid();
- int i, ret;
+ int i, fd, ret;
for (i = 0; i < MAX_NS_NESTING; i++)
if (args->pid[i] == 0)
@@ -524,6 +524,16 @@ long __export_restore_thread(struct thread_restore_args *args)
if (restore_thread_common(args))
goto core_restore_end;
+ fd = args->pfc_ns_fd;
+ if (fd >= 0) {
+ ret = sys_setns(fd, CLONE_NEWPID);
+ if (ret) {
+ pr_err("Can't setns: ret=%d\n", ret);
+ goto core_restore_end;
+ }
+ sys_close(fd);
+ }
+
ret = restore_creds(args->creds_args, args->ta->proc_fd);
if (ret)
goto core_restore_end;
@@ -1159,7 +1169,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, k;
+ int i, k, fd, self_thread;
VmaEntry *vma_entry;
unsigned long va;
struct restore_vma_io *rio;
@@ -1484,15 +1494,16 @@ long __export_restore_task(struct task_restore_args *args)
* | thread restore proc | thread1 stack | thread1 rt_sigframe |
* +--------------------------------------------------------------------------+
*/
-
+ self_thread = 0;
if (args->nr_threads > 1) {
struct thread_restore_args *thread_args = args->thread_args;
long clone_flags = CLONE_VM | CLONE_FILES | CLONE_SIGHAND |
CLONE_THREAD | CLONE_SYSVSEM | CLONE_FS;
long last_pid_len;
long parent_tid;
- int i, fd = -1;
+ int i;
+ fd = -1;
if (thread_args[0].pid[1] == 0) {
/* One level pid ns hierarhy */
fd = sys_openat(args->proc_fd, LAST_PID_PATH, O_RDWR, 0);
@@ -1507,8 +1518,10 @@ 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[0] == args->t->pid[0])
+ if (thread_args[i].pid[0] == args->t->pid[0]) {
+ self_thread = i;
continue;
+ }
if (fd >= 0) {
/* One level pid ns hierarhy */
@@ -1606,6 +1619,16 @@ long __export_restore_task(struct task_restore_args *args)
rst_tcp_socks_all(args);
+ fd = args->thread_args[self_thread].pfc_ns_fd;
+ if (fd >= 0) {
+ ret = sys_setns(fd, CLONE_NEWPID);
+ if (ret) {
+ pr_err("Can't setns: ret=%d\n", (int)ret);
+ goto core_restore_end;
+ }
+ sys_close(fd);
+ }
+
/* The kernel restricts setting seccomp to uid 0 in the current user
* ns, so we must do this before restore_creds.
*/
More information about the CRIU
mailing list