static int setup_child_handler(struct parasite_ctl *ctl) { struct sigaction sa = { .sa_sigaction = ctl->ictx.child_handler, .sa_flags = SA_SIGINFO | SA_RESTART, }; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGCHLD); if (sigaction(SIGCHLD, &sa, NULL)) { pr_perror("Unable to setup SIGCHLD handler"); return -1; } return 0; } static int restore_child_handler(struct parasite_ctl *ctl) { if (sigaction(SIGCHLD, &ctl->ictx.orig_handler, NULL)) { pr_perror("Unable to setup SIGCHLD handler"); return -1; } return 0; } static int parasite_run(pid_t pid, int cmd, unsigned long ip, void *stack, user_regs_struct_t *regs, struct thread_ctx *octx) { k_rtsigset_t block; ksigfillset(&block); if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), &block)) { pr_perror("Can't block signals for %d", pid); goto err_sig; } parasite_setup_regs(ip, stack, regs); if (ptrace_set_regs(pid, regs)) { pr_perror("Can't set registers for %d", pid); goto err_regs; } if (ptrace(cmd, pid, NULL, NULL)) { pr_perror("Can't run parasite at %d", pid); goto err_cont; } return 0; err_cont: if (ptrace_set_regs(pid, &octx->regs)) pr_perror("Can't restore regs for %d", pid); err_regs: if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), &octx->sigmask)) pr_perror("Can't restore sigmask for %d", pid); err_sig: return -1; }
static int parasite_execute_by_pid(unsigned int cmd, struct parasite_ctl *ctl, pid_t pid) { int ret; user_regs_struct_t regs_orig, regs; if (ctl->pid.real == pid) regs = ctl->regs_orig; else { if (ptrace(PTRACE_GETREGS, pid, NULL, ®s_orig)) { pr_perror("Can't obtain registers (pid: %d)", pid); return -1; } regs = regs_orig; } *ctl->addr_cmd = cmd; parasite_setup_regs(ctl->parasite_ip, ®s); ret = __parasite_execute(ctl, pid, ®s); if (ret == 0) ret = (int)REG_RES(regs); if (ret) pr_err("Parasite exited with %d\n", ret); if (ctl->pid.real != pid) if (ptrace(PTRACE_SETREGS, pid, NULL, ®s_orig)) { pr_perror("Can't restore registers (pid: %d)", pid); return -1; } return ret; }