[CRIU] [PATCH 3/7] parasite: Pass exec start point to parasite_prep_ctl

Pavel Emelyanov xemul at virtuozzo.com
Mon Sep 26 03:20:10 PDT 2016


The parasite_prep_ctl() will become compel call, so it won't
have the code that scans CRIU's vma area list. For pure compel
users we'll need to add simple /proc/maps scanner that'd find
the entry point.

Signed-off-by: Pavel Emelyanov <xemul at virtuozzo.com>
---
 criu/cr-exec.c                  |  9 ++++++++-
 criu/cr-restore.c               |  2 +-
 criu/include/parasite-syscall.h |  4 ++--
 criu/parasite-syscall.c         | 26 +++++++++++---------------
 4 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/criu/cr-exec.c b/criu/cr-exec.c
index ba38269..d7d7332 100644
--- a/criu/cr-exec.c
+++ b/criu/cr-exec.c
@@ -120,6 +120,7 @@ int cr_exec(int pid, char **opt)
 	struct vm_area_list vmas;
 	int ret, prev_state, exit_code = -1;
 	struct proc_status_creds *creds = NULL;
+	unsigned long p_start;
 
 	if (!sys_name) {
 		pr_err("Syscall name required\n");
@@ -153,7 +154,13 @@ int cr_exec(int pid, char **opt)
 		goto out_unseize;
 	}
 
-	ctl = parasite_prep_ctl(pid, &vmas);
+	p_start = get_exec_start(&vmas);
+	if (!p_start) {
+		pr_err("No suitable VM are found\n");
+		goto out_unseize;
+	}
+
+	ctl = parasite_prep_ctl(pid, p_start);
 	if (!ctl) {
 		pr_err("Can't prep ctl %d\n", pid);
 		goto out_unseize;
diff --git a/criu/cr-restore.c b/criu/cr-restore.c
index a0e16ee..7358794 100644
--- a/criu/cr-restore.c
+++ b/criu/cr-restore.c
@@ -1647,7 +1647,7 @@ static void finalize_restore(void)
 			continue;
 
 		/* Unmap the restorer blob */
-		ctl = parasite_prep_ctl(pid, NULL);
+		ctl = parasite_prep_ctl(pid, 0);
 		if (ctl == NULL)
 			continue;
 
diff --git a/criu/include/parasite-syscall.h b/criu/include/parasite-syscall.h
index 9f3311b..c5db404 100644
--- a/criu/include/parasite-syscall.h
+++ b/criu/include/parasite-syscall.h
@@ -102,8 +102,8 @@ extern struct parasite_ctl *parasite_infect_seized(pid_t pid,
 						   struct pstree_item *item,
 						   struct vm_area_list *vma_area_list);
 extern void parasite_ensure_args_size(unsigned long sz);
-extern struct parasite_ctl *parasite_prep_ctl(pid_t pid,
-					      struct vm_area_list *vma_area_list);
+extern unsigned long get_exec_start(struct vm_area_list *);
+extern struct parasite_ctl *parasite_prep_ctl(pid_t pid, unsigned long exec_start);
 extern int parasite_map_exchange(struct parasite_ctl *ctl, unsigned long size);
 
 extern int parasite_dump_cgroup(struct parasite_ctl *ctl, struct parasite_dump_cgroup_args *cgroup);
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index facb25c..cf65c19 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -44,11 +44,11 @@
 #define MEMFD_FNAME	"CRIUMFD"
 #define MEMFD_FNAME_SZ	sizeof(MEMFD_FNAME)
 
-static unsigned long get_exec_start(struct list_head *vma_area_list)
+unsigned long get_exec_start(struct vm_area_list *vmas)
 {
 	struct vma_area *vma_area;
 
-	list_for_each_entry(vma_area, vma_area_list, list) {
+	list_for_each_entry(vma_area, &vmas->h, list) {
 		unsigned long len;
 
 		if (vma_area->e->start >= kdat.task_size)
@@ -1239,7 +1239,7 @@ err:
 }
 
 /* If vma_area_list is NULL, a place for injecting syscall will not be set. */
-struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_list)
+struct parasite_ctl *parasite_prep_ctl(pid_t pid, unsigned long exec_start)
 {
 	struct parasite_ctl *ctl = NULL;
 
@@ -1263,17 +1263,7 @@ struct parasite_ctl *parasite_prep_ctl(pid_t pid, struct vm_area_list *vma_area_
 	ctl->pid.real	= pid;
 	ctl->pid.virt	= 0;
 
-	if (vma_area_list == NULL)
-		return ctl;
-
-	/* Search a place for injecting syscall */
-	ctl->syscall_ip = get_exec_start(&vma_area_list->h);
-	if (!ctl->syscall_ip) {
-		pr_err("No suitable VMA found to run parasite "
-		       "bootstrap code (pid: %d)\n", pid);
-		goto err;
-	}
-
+	ctl->syscall_ip = exec_start;
 	pr_debug("Parasite syscall_ip at %p\n", (void *)ctl->syscall_ip);
 
 	return ctl;
@@ -1477,7 +1467,13 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
 
 	BUG_ON(item->threads[0].real != pid);
 
-	ctl = parasite_prep_ctl(pid, vma_area_list);
+	p = get_exec_start(vma_area_list);
+	if (!p) {
+		pr_err("No suitable VM found\n");
+		return NULL;
+	}
+
+	ctl = parasite_prep_ctl(pid, p);
 	if (!ctl)
 		return NULL;
 
-- 
2.5.0



More information about the CRIU mailing list