2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-31 06:15:24 +00:00

ns: Restore pid_for_children ns in threads

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@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit is contained in:
Kirill Tkhai
2017-05-31 20:55:03 +03:00
committed by Andrei Vagin
parent f39a52923d
commit ecb7e5801a
3 changed files with 53 additions and 5 deletions

View File

@@ -3109,6 +3109,25 @@ out:
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) {}
@@ -3583,12 +3602,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]);

View File

@@ -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);

View File

@@ -506,7 +506,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)
@@ -530,6 +530,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;
@@ -1190,7 +1200,7 @@ static bool vdso_needs_parking(struct task_restore_args *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;
@@ -1526,15 +1536,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);
@@ -1549,8 +1560,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 */
@@ -1648,6 +1661,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.
*/