[CRIU] [PATCH 11/24] dump: save registers when the task is already infected

Andrey Vagin avagin at openvz.org
Wed May 22 16:08:12 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 162566b..04079db 100644
--- a/arch/arm/crtools.c
+++ b/arch/arm/crtools.c
@@ -86,21 +86,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, &regs)) {
-		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 8683851..8d12031 100644
--- a/arch/x86/crtools.c
+++ b/arch/x86/crtools.c
@@ -107,21 +107,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, &regs)) {
-		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 */
@@ -187,12 +181,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 fa6e237..278407b 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -1361,26 +1361,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;
@@ -1403,9 +1383,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 9dca5c6..0452e4f 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -691,6 +691,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;
 	}
@@ -945,6 +951,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;
@@ -975,6 +984,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