mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-02 15:25:21 +00:00
rst: Fix creds vs threads restoration
Writing to last_pid sysctl is CAP_SYS_ADMIN potected. Thus restoring creds before it won't work in all the cases. Fix this by making all threads restore creds themselves, and the thread group leader -- after all of them. Signed-off-by: Pavel Emelyanov <xemul@parallels.com> Acked-by: Andrey Vagin <avagin@parallels.com>
This commit is contained in:
@@ -1495,7 +1495,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core, struct list_head *tgt_v
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
mutex_init(&task_args->t._rst_lock);
|
mutex_init(&task_args->rst_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now prepare run-time data for threads restore.
|
* Now prepare run-time data for threads restore.
|
||||||
@@ -1537,7 +1537,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core, struct list_head *tgt_v
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_args[i].rst_lock = &task_args->t._rst_lock;
|
thread_args[i].ta = task_args;
|
||||||
thread_args[i].gpregs = *core->thread_info->gpregs;
|
thread_args[i].gpregs = *core->thread_info->gpregs;
|
||||||
thread_args[i].clear_tid_addr = core->thread_info->clear_tid_addr;
|
thread_args[i].clear_tid_addr = core->thread_info->clear_tid_addr;
|
||||||
|
|
||||||
|
@@ -62,6 +62,8 @@ struct rst_sched_param {
|
|||||||
int prio;
|
int prio;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct task_restore_core_args;
|
||||||
|
|
||||||
/* Make sure it's pow2 in size */
|
/* Make sure it's pow2 in size */
|
||||||
struct thread_restore_args {
|
struct thread_restore_args {
|
||||||
struct restore_mem_zone mem_zone;
|
struct restore_mem_zone mem_zone;
|
||||||
@@ -76,10 +78,7 @@ struct thread_restore_args {
|
|||||||
|
|
||||||
struct rst_sched_param sp;
|
struct rst_sched_param sp;
|
||||||
|
|
||||||
union {
|
struct task_restore_core_args *ta;
|
||||||
mutex_t _rst_lock;
|
|
||||||
mutex_t *rst_lock;
|
|
||||||
};
|
|
||||||
} __aligned(sizeof(long));
|
} __aligned(sizeof(long));
|
||||||
|
|
||||||
struct task_restore_core_args {
|
struct task_restore_core_args {
|
||||||
@@ -90,6 +89,8 @@ struct task_restore_core_args {
|
|||||||
int logfd;
|
int logfd;
|
||||||
unsigned int loglevel;
|
unsigned int loglevel;
|
||||||
|
|
||||||
|
mutex_t rst_lock;
|
||||||
|
|
||||||
/* threads restoration */
|
/* threads restoration */
|
||||||
int nr_threads; /* number of threads */
|
int nr_threads; /* number of threads */
|
||||||
thread_restore_fcall_t clone_restore_fn; /* helper address for clone() call */
|
thread_restore_fcall_t clone_restore_fn; /* helper address for clone() call */
|
||||||
|
22
restorer.c
22
restorer.c
@@ -224,7 +224,9 @@ long __export_restore_thread(struct thread_restore_args *args)
|
|||||||
if (restore_thread_common(rt_sigframe, args))
|
if (restore_thread_common(rt_sigframe, args))
|
||||||
goto core_restore_end;
|
goto core_restore_end;
|
||||||
|
|
||||||
mutex_unlock(args->rst_lock);
|
mutex_unlock(&args->ta->rst_lock);
|
||||||
|
|
||||||
|
restore_creds(&args->ta->creds);
|
||||||
|
|
||||||
futex_dec_and_wake(&task_entries->nr_in_progress);
|
futex_dec_and_wake(&task_entries->nr_in_progress);
|
||||||
|
|
||||||
@@ -529,14 +531,6 @@ long __export_restore_task(struct task_restore_core_args *args)
|
|||||||
goto core_restore_end;
|
goto core_restore_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* last-pid is CAP_SYS_ADMIN protected, thus restore creds
|
|
||||||
* _after_ opening that file, but before fork to make threads
|
|
||||||
* inherit them properly
|
|
||||||
*/
|
|
||||||
|
|
||||||
restore_creds(&args->creds);
|
|
||||||
|
|
||||||
ret = sys_flock(fd, LOCK_EX);
|
ret = sys_flock(fd, LOCK_EX);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Can't lock last_pid %d\n", fd);
|
pr_err("Can't lock last_pid %d\n", fd);
|
||||||
@@ -550,7 +544,7 @@ long __export_restore_task(struct task_restore_core_args *args)
|
|||||||
if (thread_args[i].pid == args->t.pid)
|
if (thread_args[i].pid == args->t.pid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mutex_lock(&args->t._rst_lock);
|
mutex_lock(&args->rst_lock);
|
||||||
|
|
||||||
new_sp =
|
new_sp =
|
||||||
RESTORE_ALIGN_STACK((long)thread_args[i].mem_zone.stack,
|
RESTORE_ALIGN_STACK((long)thread_args[i].mem_zone.stack,
|
||||||
@@ -613,7 +607,13 @@ long __export_restore_task(struct task_restore_core_args *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sys_close(fd);
|
sys_close(fd);
|
||||||
} else
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writing to last-pid is CAP_SYS_ADMIN protected, thus restore
|
||||||
|
* creds _after_ all threads creation.
|
||||||
|
*/
|
||||||
|
|
||||||
restore_creds(&args->creds);
|
restore_creds(&args->creds);
|
||||||
|
|
||||||
futex_dec_and_wake(&args->task_entries->nr_in_progress);
|
futex_dec_and_wake(&args->task_entries->nr_in_progress);
|
||||||
|
Reference in New Issue
Block a user