struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, struct vm_area_list *vma_area_list, struct parasite_drain_fd *dfds) { int ret; struct parasite_ctl *ctl; ctl = parasite_prep_ctl(pid, vma_area_list); if (!ctl) return NULL; /* * Inject a parasite engine. Ie allocate memory inside alien * space and copy engine code there. Then re-map the engine * locally, so we will get an easy way to access engine memory * without using ptrace at all. */ ctl->args_size = parasite_args_size(vma_area_list, dfds); ret = parasite_map_exchange(ctl, parasite_size + ctl->args_size); if (ret) goto err_restore; pr_info("Putting parasite blob into %p->%p\n", ctl->local_map, ctl->remote_map); memcpy(ctl->local_map, parasite_blob, sizeof(parasite_blob)); /* Setup the rest of a control block */ ctl->parasite_ip = (unsigned long)parasite_sym(ctl->remote_map, __export_parasite_head_start); ctl->addr_cmd = parasite_sym(ctl->local_map, __export_parasite_cmd); ctl->addr_args = parasite_sym(ctl->local_map, __export_parasite_args); ret = parasite_init(ctl, pid, item->nr_threads); if (ret) { pr_err("%d: Can't create a transport socket\n", pid); goto err_restore; } ctl->signals_blocked = 1; ret = parasite_set_logfd(ctl, pid); if (ret) { pr_err("%d: Can't set a logging descriptor\n", pid); goto err_restore; } ret = parasite_init_threads_seized(ctl, item); if (ret) goto err_restore; return ctl; err_restore: parasite_cure_seized(ctl, item); return NULL; }
int __used parasite_service(unsigned long cmd, void *args) { BUILD_BUG_ON(sizeof(struct parasite_dump_pages_args) > PARASITE_ARG_SIZE); BUILD_BUG_ON(sizeof(struct parasite_init_args) > PARASITE_ARG_SIZE); BUILD_BUG_ON(sizeof(struct parasite_dump_misc) > PARASITE_ARG_SIZE); BUILD_BUG_ON(sizeof(struct parasite_dump_tid_info) > PARASITE_ARG_SIZE); BUILD_BUG_ON(sizeof(struct parasite_drain_fd) > PARASITE_ARG_SIZE); switch (cmd) { case PARASITE_CMD_INIT: return init((struct parasite_init_args *) args); case PARASITE_CMD_FINI: return fini(); case PARASITE_CMD_SET_LOGFD: return parasite_set_logfd(); case PARASITE_CMD_DUMPPAGES_INIT: return dump_pages_init(); case PARASITE_CMD_DUMPPAGES_FINI: return dump_pages_fini(); case PARASITE_CMD_DUMPPAGES: return dump_pages((struct parasite_dump_pages_args *)args); case PARASITE_CMD_DUMP_SIGACTS: return dump_sigact((struct parasite_dump_sa_args *)args); case PARASITE_CMD_DUMP_ITIMERS: return dump_itimers((struct parasite_dump_itimers_args *)args); case PARASITE_CMD_DUMP_MISC: return dump_misc((struct parasite_dump_misc *)args); case PARASITE_CMD_DUMP_TID_ADDR: return dump_tid_info((struct parasite_dump_tid_info *)args); case PARASITE_CMD_DRAIN_FDS: return drain_fds((struct parasite_drain_fd *)args); case PARASITE_CMD_GET_PROC_FD: return parasite_get_proc_fd(); #ifdef CONFIG_HAS_TLS case PARASITE_CMD_GET_TLS: parasite_get_tls((struct parasite_get_tls_args*)args); return 0; #endif } sys_write_msg("Unknown command to parasite\n"); return -EINVAL; }