From 89d8b20186ec544b95ea5d2e0046bf9c6fc272f4 Mon Sep 17 00:00:00 2001 From: Andrey Vagin Date: Mon, 23 Sep 2013 14:33:35 +0400 Subject: [PATCH] restorer: unmap itself (v2) This patch adds a function for removing the restorer blob. This function never returns and the process must be trapped on the exit from the munmap syscall. v2: * release parasite_ctl sturcture and use the new interface of parasite_prep_ctl Signed-off-by: Andrey Vagin Signed-off-by: Pavel Emelyanov --- cr-restore.c | 28 +++++++++++++++++++++++----- include/crtools.h | 2 ++ include/restorer.h | 3 +++ pie/restorer.c | 14 ++++++++++++++ 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/cr-restore.c b/cr-restore.c index a0b442fec..67fd15e71 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -1362,6 +1362,7 @@ static void finalize_restore(int status) for_each_pstree_item(item) { pid_t pid = item->pid.real; + struct parasite_ctl *ctl; int i; if (item->state == TASK_DEAD) @@ -1373,7 +1374,16 @@ static void finalize_restore(int status) if (status < 0) goto detach; - /* TODO Unmap the restorer blob and restore the process state */ + /* Unmap the restorer blob */ + ctl = parasite_prep_ctl(pid, NULL); + if (ctl == NULL) + goto detach; + + parasite_unmap(ctl, (unsigned long) item->rst->munmap_restorer); + + xfree(ctl); + + /* TODO restore the process state */ detach: for (i = 0; i < item->nr_threads; i++) { pid = item->threads[i].real; @@ -2206,6 +2216,8 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core) long new_sp, exec_mem_hint; long ret; + + void *bootstrap_start; long restore_bootstrap_len; struct task_restore_core_args *task_args; @@ -2314,6 +2326,8 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core) vdso_rt_size = vdso_rt_vma_size + vdso_rt_delta; } + restore_bootstrap_len += vdso_rt_size; + /* * Restorer is a blob (code + args) that will get mapped in some * place, that should _not_ intersect with both -- current mappings @@ -2326,16 +2340,16 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core) */ exec_mem_hint = restorer_get_vma_hint(pid, &rst_vmas.h, &self_vmas.h, - restore_bootstrap_len + - vdso_rt_size); + restore_bootstrap_len); + bootstrap_start = (void *) exec_mem_hint; if (exec_mem_hint == -1) { pr_err("No suitable area for task_restore bootstrap (%ldK)\n", - restore_bootstrap_len + vdso_rt_size); + restore_bootstrap_len); goto err; } pr_info("Found bootstrap VMA hint at: 0x%lx (needs ~%ldK)\n", exec_mem_hint, - KBYTES(restore_bootstrap_len + vdso_rt_size)); + KBYTES(restore_bootstrap_len)); ret = remap_restorer_blob((void *)exec_mem_hint); if (ret < 0) @@ -2347,6 +2361,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core) */ restore_thread_exec_start = restorer_sym(exec_mem_hint, __export_restore_thread); restore_task_exec_start = restorer_sym(exec_mem_hint, __export_restore_task); + current->rst->munmap_restorer = restorer_sym(exec_mem_hint, __export_unmap); exec_mem_hint += restorer_len; @@ -2364,6 +2379,9 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core) task_args = mem; thread_args = mem + restore_task_vma_len; + task_args->bootstrap_start = bootstrap_start; + task_args->bootstrap_len = restore_bootstrap_len; + /* * Get a reference to shared memory area which is * used to signal if shmem restoration complete diff --git a/include/crtools.h b/include/crtools.h index a574b4631..02c6bd37c 100644 --- a/include/crtools.h +++ b/include/crtools.h @@ -177,6 +177,8 @@ struct rst_info { unsigned long premmapped_len; unsigned long clone_flags; + void *munmap_restorer; + int nr_zombies; int service_fd_id; diff --git a/include/restorer.h b/include/restorer.h index 1ed1d81ae..ae762d7cc 100644 --- a/include/restorer.h +++ b/include/restorer.h @@ -126,6 +126,9 @@ struct task_restore_core_args { unsigned long premmapped_len; rt_sigaction_t sigchld_act; + void *bootstrap_start; + unsigned long bootstrap_len; + struct itimerval itimers[3]; int timer_n; diff --git a/pie/restorer.c b/pie/restorer.c index a9ab178cc..8e4360963 100644 --- a/pie/restorer.c +++ b/pie/restorer.c @@ -511,6 +511,17 @@ static void restore_posix_timers(struct task_restore_core_args *args) sys_timer_settime((timer_t)rt->spt.it_id, 0, &rt->val, NULL); } } +static void *bootstrap_start; +static unsigned int bootstrap_len; + +void __export_unmap(void) +{ + sys_munmap(bootstrap_start, bootstrap_len); + /* + * sys_munmap must not return here. The controll process must + * trap us on the exit from sys_munmap. + */ +} /* * The main routine to restore task via sigreturn. @@ -532,6 +543,9 @@ long __export_restore_task(struct task_restore_core_args *args) pid_t my_pid = sys_getpid(); rt_sigaction_t act; + bootstrap_start = args->bootstrap_start; + bootstrap_len = args->bootstrap_len; + task_entries = args->task_entries; ksigfillset(&act.rt_sa_mask);