diff --git a/include/parasite.h b/include/parasite.h index e9672ac5c..4e2696760 100644 --- a/include/parasite.h +++ b/include/parasite.h @@ -25,6 +25,7 @@ enum { PARASITE_CMD_INIT_DAEMON, PARASITE_CMD_DUMP_THREAD, + PARASITE_CMD_UNMAP, /* * These two must be greater than INITs. @@ -70,6 +71,11 @@ struct parasite_init_args { struct rt_sigframe *sigframe; }; +struct parasite_unmap_args { + void *parasite_start; + unsigned long parasite_len; +}; + struct parasite_vma_entry { unsigned long start; diff --git a/parasite-syscall.c b/parasite-syscall.c index 48d0785be..40a9167af 100644 --- a/parasite-syscall.c +++ b/parasite-syscall.c @@ -307,14 +307,6 @@ int parasite_execute_daemon(unsigned int cmd, struct parasite_ctl *ctl) return ret; } -static int munmap_seized(struct parasite_ctl *ctl, void *addr, size_t length) -{ - unsigned long x; - - return syscall_seized(ctl, __NR_munmap, &x, - (unsigned long)addr, length, 0, 0, 0, 0); -} - static int gen_parasite_saddr(struct sockaddr_un *saddr, int key) { int sun_len; @@ -850,10 +842,15 @@ int parasite_cure_remote(struct parasite_ctl *ctl) close_safe(&ctl->tsock); if (ctl->remote_map) { - if (munmap_seized(ctl, (void *)ctl->remote_map, ctl->map_length)) { - pr_err("munmap_seized failed (pid: %d)\n", ctl->pid.real); + struct parasite_unmap_args *args; + + *ctl->addr_cmd = PARASITE_CMD_UNMAP; + + args = parasite_args(ctl, struct parasite_unmap_args); + args->parasite_start = ctl->remote_map; + args->parasite_len = ctl->map_length; + if (parasite_unmap(ctl, ctl->parasite_ip)) ret = -1; - } } return ret; diff --git a/pie/parasite.c b/pie/parasite.c index 50435d07c..927cc83a1 100644 --- a/pie/parasite.c +++ b/pie/parasite.c @@ -478,6 +478,20 @@ out: return 0; } +static noinline int unmap_itself(void *data) +{ + struct parasite_unmap_args *args = data; + + sys_munmap(args->parasite_start, args->parasite_len); + /* + * sys_munmap never return back. The controll process must + * trap us on the exit from munmap + */ + + BUG(); + return -1; +} + static noinline __used int parasite_init_daemon(void *data) { struct parasite_init_args *args = data; @@ -523,6 +537,8 @@ int __used parasite_service(unsigned int cmd, void *args) return dump_thread(args); case PARASITE_CMD_INIT_DAEMON: return parasite_init_daemon(args); + case PARASITE_CMD_UNMAP: + return unmap_itself(args); } pr_err("Unknown command to parasite: %d\n", cmd);