From 64ecb2746c74644f13cda07e473e0fabac89e275 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Fri, 24 May 2013 16:20:14 +0400 Subject: [PATCH] dump: save registers when the task is already infected Otherwise a task can start to handle a signal and registers can be changed. Signed-off-by: Andrey Vagin Signed-off-by: Pavel Emelyanov --- arch/arm/crtools.c | 10 ++-------- arch/arm/include/asm/dump.h | 2 +- arch/x86/crtools.c | 12 +++--------- arch/x86/include/asm/dump.h | 2 +- cr-dump.c | 23 ----------------------- parasite-syscall.c | 16 ++++++++++++++++ 6 files changed, 23 insertions(+), 42 deletions(-) diff --git a/arch/arm/crtools.c b/arch/arm/crtools.c index 45c43e9b9..587287410 100644 --- a/arch/arm/crtools.c +++ b/arch/arm/crtools.c @@ -89,21 +89,15 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret, #define assign_reg(dst, src, e) dst->e = (__typeof__(dst->e))src.ARM_##e #define PTRACE_GETVFPREGS 27 -int get_task_regs(pid_t pid, CoreEntry *core) +int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core) { - user_regs_struct_t regs = {{-1}}; struct user_vfp vfp; int ret = -1; pr_info("Dumping GP/FPU registers for %d\n", pid); - if (ptrace(PTRACE_GETREGS, pid, NULL, ®s)) { - pr_err("Can't obtain GP registers for %d\n", pid); - goto err; - } - if (ptrace(PTRACE_GETVFPREGS, pid, NULL, &vfp)) { - pr_err("Can't obtain FPU registers for %d\n", pid); + pr_perror("Can't obtain FPU registers for %d", pid); goto err; } diff --git a/arch/arm/include/asm/dump.h b/arch/arm/include/asm/dump.h index 1f2098073..f81b3a695 100644 --- a/arch/arm/include/asm/dump.h +++ b/arch/arm/include/asm/dump.h @@ -1,7 +1,7 @@ #ifndef __CR_ASM_DUMP_H__ #define __CR_ASM_DUMP_H__ -extern int get_task_regs(pid_t pid, CoreEntry *core); +extern int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core); extern int arch_alloc_thread_info(CoreEntry *core); extern void arch_free_thread_info(CoreEntry *core); diff --git a/arch/x86/crtools.c b/arch/x86/crtools.c index 2d26aacc8..98f047da7 100644 --- a/arch/x86/crtools.c +++ b/arch/x86/crtools.c @@ -110,21 +110,15 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret, return 0; } -int get_task_regs(pid_t pid, CoreEntry *core) +int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core) { struct xsave_struct xsave = { }; - user_regs_struct_t regs = {-1}; struct iovec iov; int ret = -1; pr_info("Dumping GP/FPU registers for %d\n", pid); - if (ptrace(PTRACE_GETREGS, pid, NULL, ®s)) { - pr_err("Can't obtain GP registers for %d\n", pid); - goto err; - } - /* Did we come from a system call? */ if ((int)regs.orig_ax >= 0) { /* Restart the system call */ @@ -190,12 +184,12 @@ int get_task_regs(pid_t pid, CoreEntry *core) iov.iov_len = sizeof(xsave); if (ptrace(PTRACE_GETREGSET, pid, (unsigned int)NT_X86_XSTATE, &iov) < 0) { - pr_err("Can't obtain FPU registers for %d\n", pid); + pr_perror("Can't obtain FPU registers for %d", pid); goto err; } } else { if (ptrace(PTRACE_GETFPREGS, pid, NULL, &xsave)) { - pr_err("Can't obtain FPU registers for %d\n", pid); + pr_perror("Can't obtain FPU registers for %d", pid); goto err; } } diff --git a/arch/x86/include/asm/dump.h b/arch/x86/include/asm/dump.h index 1013981f8..1505fd298 100644 --- a/arch/x86/include/asm/dump.h +++ b/arch/x86/include/asm/dump.h @@ -1,7 +1,7 @@ #ifndef __CR_ASM_DUMP_H__ #define __CR_ASM_DUMP_H__ -extern int get_task_regs(pid_t pid, CoreEntry *core); +extern int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core); extern int arch_alloc_thread_info(CoreEntry *core); extern void arch_free_thread_info(CoreEntry *core); diff --git a/cr-dump.c b/cr-dump.c index 0738b2cb6..7d1bec67b 100644 --- a/cr-dump.c +++ b/cr-dump.c @@ -1364,26 +1364,6 @@ err_cure: goto err_free; } -static int collect_regs_seized(struct pstree_item *item) -{ - unsigned int i; - int ret; - - if (pstree_alloc_cores(item)) - return -1; - - for (i = 0; i < item->nr_threads; i++) { - pid_t pid = item->threads[i].real; - ret = get_task_regs(pid, item->core[i]); - if (ret) { - pr_err("Can't obtain regs for thread %d\n", pid); - return -1; - } - } - - return 0; -} - static int dump_one_task(struct pstree_item *item) { pid_t pid = item->pid.real; @@ -1406,9 +1386,6 @@ static int dump_one_task(struct pstree_item *item) if (item->state == TASK_DEAD) return 0; - if (collect_regs_seized(item)) - return -1; - dfds = xmalloc(sizeof(*dfds)); if (!dfds) goto err_free; diff --git a/parasite-syscall.c b/parasite-syscall.c index 4c8c1771e..510767ee0 100644 --- a/parasite-syscall.c +++ b/parasite-syscall.c @@ -675,6 +675,13 @@ int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i item->threads[i].real); break; } + + ret = get_task_regs(tid, ctl->threads[i].regs_orig, item->core[i]); + if (ret) { + pr_err("Can't obtain regs for thread %d\n", tid); + break; + } + } return ret; @@ -891,6 +898,9 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, BUG_ON(item->threads[0].real != pid); + if (pstree_alloc_cores(item)) + return NULL; + ctl = parasite_prep_ctl(pid, vma_area_list, item->nr_threads); if (!ctl) return NULL; @@ -930,6 +940,12 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, goto err_restore; } + ret = get_task_regs(pid, ctl->threads[0].regs_orig, item->core[0]); + if (ret) { + pr_err("Can't obtain regs for thread %d\n", pid); + goto err_restore; + } + ctl->signals_blocked = 1; ret = parasite_set_logfd(ctl, pid);