From 78a3670ba8cfba066f75fee154cfec76f8b471e0 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Mon, 26 Sep 2016 13:20:00 +0300 Subject: [PATCH] parasite: Pass exec start point to parasite_prep_ctl 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 --- 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 ce22f505a..09866129e 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"); @@ -159,7 +160,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 9f0d3fabd..589d46630 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -1536,7 +1536,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 6d9a90327..e47682cf6 100644 --- a/criu/include/parasite-syscall.h +++ b/criu/include/parasite-syscall.h @@ -99,8 +99,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 6b4f865c1..fdc96e8c7 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) @@ -1144,7 +1144,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; @@ -1168,17 +1168,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; @@ -1365,7 +1355,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;