[CRIU] [PATCH 06/21] parasite: save thread registers in parasite_thread_ctl

Andrey Vagin avagin at openvz.org
Fri May 24 08:20:09 EDT 2013


Now we restore thread registers immediately after a command,
but when we will execute a parasite, it will be impossible.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 arch/arm/crtools.c         |  2 +-
 arch/x86/crtools.c         |  2 +-
 include/parasite-syscall.h |  2 +-
 parasite-syscall.c         | 30 +++++++++++++-----------------
 4 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/arch/arm/crtools.c b/arch/arm/crtools.c
index a64a86c..81a819a 100644
--- a/arch/arm/crtools.c
+++ b/arch/arm/crtools.c
@@ -62,7 +62,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
 		unsigned long arg5,
 		unsigned long arg6)
 {
-	user_regs_struct_t regs = ctl->regs_orig;
+	user_regs_struct_t regs = ctl->threads[0].regs_orig;
 	int err;
 
 	regs.ARM_r7 = (unsigned long)nr;
diff --git a/arch/x86/crtools.c b/arch/x86/crtools.c
index 284f2c0..1fc0b63 100644
--- a/arch/x86/crtools.c
+++ b/arch/x86/crtools.c
@@ -86,7 +86,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
 		unsigned long arg5,
 		unsigned long arg6)
 {
-	user_regs_struct_t regs = ctl->regs_orig;
+	user_regs_struct_t regs = ctl->threads[0].regs_orig;
 	int err;
 
 	regs.ax  = (unsigned long)nr;
diff --git a/include/parasite-syscall.h b/include/parasite-syscall.h
index ffffaf6..689fe90 100644
--- a/include/parasite-syscall.h
+++ b/include/parasite-syscall.h
@@ -8,6 +8,7 @@
 struct parasite_thread_ctl
 {
 	pid_t			tid;
+	user_regs_struct_t	regs_orig;				/* original registers */
 };
 
 /* parasite control block */
@@ -18,7 +19,6 @@ struct parasite_ctl {
 	unsigned long		map_length;
 
 	unsigned long		parasite_ip;				/* service routine start ip */
-	user_regs_struct_t	regs_orig;				/* original registers */
 	unsigned long		syscall_ip;				/* entry point of infection */
 	u8			code_orig[BUILTIN_SYSCALL_SIZE];
 
diff --git a/parasite-syscall.c b/parasite-syscall.c
index deca9cd..b82fc7c 100644
--- a/parasite-syscall.c
+++ b/parasite-syscall.c
@@ -126,7 +126,7 @@ retry_signal:
 		 * and retry.
 		 */
 
-		if (ptrace(PTRACE_SETREGS, pid, NULL, &ctl->regs_orig)) {
+		if (ptrace(PTRACE_SETREGS, pid, NULL, &ctl->threads[0].regs_orig)) {
 			pr_perror("Can't set registers (pid: %d)", pid);
 			goto err;
 		}
@@ -169,7 +169,7 @@ retry_signal:
 				pr_perror("Can't obtain registers (pid: %d)", pid);
 				goto err;
 			}
-			ctl->regs_orig = r;
+			ctl->threads[0].regs_orig = r;
 		}
 
 		goto again;
@@ -198,19 +198,9 @@ void *parasite_args_s(struct parasite_ctl *ctl, int args_size)
 static int parasite_execute_trap_by_id(unsigned int cmd, struct parasite_ctl *ctl, int id)
 {
 	struct parasite_thread_ctl *thread = &ctl->threads[id];
+	user_regs_struct_t regs = thread->regs_orig;
 	pid_t pid = thread->tid;
 	int ret;
-	user_regs_struct_t regs_orig, regs;
-
-	if (ctl->pid.real == pid)
-		regs = ctl->regs_orig;
-	else {
-		if (ptrace(PTRACE_GETREGS, pid, NULL, &regs_orig)) {
-			pr_perror("Can't obtain registers (pid: %d)", pid);
-			return -1;
-		}
-		regs = regs_orig;
-	}
 
 	*ctl->addr_cmd = cmd;
 
@@ -224,7 +214,7 @@ static int parasite_execute_trap_by_id(unsigned int cmd, struct parasite_ctl *ct
 		pr_err("Parasite exited with %d\n", ret);
 
 	if (ctl->pid.real != pid)
-		if (ptrace(PTRACE_SETREGS, pid, NULL, &regs_orig)) {
+		if (ptrace(PTRACE_SETREGS, pid, NULL, &thread->regs_orig)) {
 			pr_perror("Can't restore registers (pid: %d)", pid);
 			return -1;
 		}
@@ -543,12 +533,18 @@ int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *i
 
 	for (i = 1; i < item->nr_threads; i++) {
 		pid_t tid = item->threads[i].real;
+		user_regs_struct_t *regs_orig = &ctl->threads[i].regs_orig;
 
 		ctl->threads[i].tid = tid;
 		ctl->nr_threads++;
 
 		args->id = i;
 
+		ret = ptrace(PTRACE_GETREGS, tid, NULL, regs_orig);
+		if (ret) {
+			pr_perror("Can't obtain registers (pid: %d)", tid);
+			break;
+		}
 
 		ret = parasite_execute_trap_by_id(PARASITE_CMD_INIT_THREAD, ctl, i);
 		if (ret) {
@@ -629,7 +625,7 @@ int parasite_cure_remote(struct parasite_ctl *ctl)
 		ret = -1;
 	}
 
-	if (ptrace(PTRACE_SETREGS, ctl->pid.real, NULL, &ctl->regs_orig)) {
+	if (ptrace(PTRACE_SETREGS, ctl->pid.real, NULL, &ctl->threads[0].regs_orig)) {
 		pr_err("Can't restore registers (pid: %d)\n", ctl->pid.real);
 		ret = -1;
 	}
@@ -686,12 +682,12 @@ struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_
 	ctl->nr_threads = 1;
 	ctl->threads[0].tid = pid;
 
-	if (ptrace(PTRACE_GETREGS, pid, NULL, &ctl->regs_orig)) {
+	if (ptrace(PTRACE_GETREGS, pid, NULL, &ctl->threads[0].regs_orig)) {
 		pr_err("Can't obtain registers (pid: %d)\n", pid);
 		goto err;
 	}
 
-	vma_area = get_vma_by_ip(&vma_area_list->h, REG_IP(ctl->regs_orig));
+	vma_area = get_vma_by_ip(&vma_area_list->h, REG_IP(ctl->threads[0].regs_orig));
 	if (!vma_area) {
 		pr_err("No suitable VMA found to run parasite "
 		       "bootstrap code (pid: %d)\n", pid);
-- 
1.8.2



More information about the CRIU mailing list