[CRIU] [PATCH 11/21] dump: save registers when the task is already infected
Andrey Vagin
avagin at openvz.org
Fri May 24 08:20:14 EDT 2013
Otherwise a task can start to handle a signal and registers can be
changed.
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
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 | 15 +++++++++++++++
6 files changed, 22 insertions(+), 42 deletions(-)
diff --git a/arch/arm/crtools.c b/arch/arm/crtools.c
index e06f03c..7c9c50e 100644
--- a/arch/arm/crtools.c
+++ b/arch/arm/crtools.c
@@ -88,21 +88,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 1f20980..f81b3a6 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 b5a0858..5f525de 100644
--- a/arch/x86/crtools.c
+++ b/arch/x86/crtools.c
@@ -109,21 +109,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 */
@@ -189,12 +183,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 1013981..1505fd2 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 73e021d..33a66e9 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1363,26 +1363,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;
@@ -1405,9 +1385,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 490082d..e2824ab 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -693,6 +693,12 @@ int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i
goto err;
}
+ 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);
+ goto err;
+ }
+
if (parasite_daemonize(ctl, i))
goto err;
}
@@ -947,6 +953,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;
@@ -986,6 +995,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);
--
1.8.2
More information about the CRIU
mailing list