[CRIU] [PATCH 1/4] ptrace: start tracing processes before restoring creds
Tycho Andersen
tycho.andersen at canonical.com
Wed Dec 16 08:15:07 PST 2015
From: Andrew Vagin <avagin at virtuozzo.com>
In order to restore seccomp correctly, we need to do it before
restore_creds() in the restorer blob. But, if the seccomp policy forbids
e.g. prctl, if the task doesn't have SUSPEND_SECCOMP set it will die when
trying to restore creds. To solve this, we break attach_to_tasks up into
two parts: 1. we attach and set SUSPEND_SECCOMP (but let the tasks continue
normally), and then after the RESTORE_CREDS stage we 2. attach to the tasks
and stop them on the final sigreturn.
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
cr-restore.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 47 insertions(+), 14 deletions(-)
diff --git a/cr-restore.c b/cr-restore.c
index 3c636b9..6815879 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1645,13 +1645,13 @@ static int restore_switch_stage(int next_stage)
return restore_wait_inprogress_tasks();
}
-static int attach_to_tasks(bool root_seized, enum trace_flags *flag)
+static int attach_to_tasks(bool root_seized)
{
struct pstree_item *item;
for_each_pstree_item(item) {
pid_t pid = item->pid.real;
- int status, i, ret;
+ int status, i;
if (!task_alive(item))
continue;
@@ -1663,21 +1663,16 @@ static int attach_to_tasks(bool root_seized, enum trace_flags *flag)
pid = item->threads[i].real;
if (item != root_item || !root_seized || i != 0) {
- if (ptrace(PTRACE_ATTACH, pid, 0, 0)) {
+ if (ptrace(PTRACE_SEIZE, pid, 0, 0)) {
pr_perror("Can't attach to %d", pid);
return -1;
}
- } else {
- /*
- * Root item is SEIZE-d, so we only need
- * to stop one (INTERRUPT) to make wait4
- * and SYSCALL below work.
- */
- if (ptrace(PTRACE_INTERRUPT, pid, 0, 0)) {
- pr_perror("Can't interrupt the %d task", pid);
- return -1;
- }
}
+ if (ptrace(PTRACE_INTERRUPT, pid, 0, 0)) {
+ pr_perror("Can't interrupt the %d task", pid);
+ return -1;
+ }
+
if (wait4(pid, &status, __WALL, NULL) != pid) {
pr_perror("waitpid(%d) failed", pid);
@@ -1694,6 +1689,43 @@ static int attach_to_tasks(bool root_seized, enum trace_flags *flag)
if (rsti(item)->has_seccomp && suspend_seccomp(pid) < 0)
pr_err("failed to suspend seccomp, restore will probably fail...\n");
+ if (ptrace(PTRACE_CONT, pid, NULL, NULL) ) {
+ pr_perror("Unable to resume %d", pid);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int catch_tasks(bool root_seized, enum trace_flags *flag)
+{
+ struct pstree_item *item;
+
+ for_each_pstree_item(item) {
+ pid_t pid = item->pid.real;
+ int status, i, ret;
+
+ if (!task_alive(item))
+ continue;
+
+ if (parse_threads(item->pid.real, &item->threads, &item->nr_threads))
+ return -1;
+
+ for (i = 0; i < item->nr_threads; i++) {
+ pid = item->threads[i].real;
+
+ if (ptrace(PTRACE_INTERRUPT, pid, 0, 0)) {
+ pr_perror("Can't interrupt the %d task", pid);
+ return -1;
+ }
+
+ if (wait4(pid, &status, __WALL, NULL) != pid) {
+ pr_perror("waitpid(%d) failed", pid);
+ return -1;
+ }
+
ret = ptrace_stop_pie(pid, rsti(item)->breakpoint, flag);
if (ret < 0)
return -1;
@@ -1931,13 +1963,14 @@ static int restore_root_task(struct pstree_item *init)
* -------------------------------------------------------------
* Below this line nothing should fail, because network is unlocked
*/
+ attach_to_tasks(root_as_sibling);
ret = restore_switch_stage(CR_STATE_RESTORE_CREDS);
BUG_ON(ret);
timing_stop(TIME_RESTORE);
- ret = attach_to_tasks(root_as_sibling, &flag);
+ ret = catch_tasks(root_as_sibling, &flag);
pr_info("Restore finished successfully. Resuming tasks.\n");
futex_set_and_wake(&task_entries->start, CR_STATE_COMPLETE);
--
2.5.0
More information about the CRIU
mailing list