Index: sys/kern/sys_ptrace_common.c =================================================================== RCS file: /cvsroot/src/sys/kern/sys_ptrace_common.c,v retrieving revision 1.65 diff -u -r1.65 sys_ptrace_common.c --- sys/kern/sys_ptrace_common.c 8 Oct 2019 12:29:57 -0000 1.65 +++ sys/kern/sys_ptrace_common.c 9 Oct 2019 12:53:30 -0000 @@ -286,6 +286,7 @@ case PT_DUMPCORE: case PT_RESUME: case PT_SUSPEND: + case PT_STOP: result = KAUTH_RESULT_ALLOW; break; @@ -493,6 +494,7 @@ case PT_GET_PROCESS_STATE: case PT_RESUME: case PT_SUSPEND: + case PT_STOP: /* * You can't do what you want to the process if: * (1) It's not being traced at all, @@ -511,8 +513,11 @@ /* * (3) it's not currently stopped. + * + * As an exception allow PT_KILL and PT_STOP here. */ - if (t->p_stat != SSTOP || !t->p_waited /* XXXSMP */) { + if (req != PT_KILL && req != PT_STOP && + (t->p_stat != SSTOP || !t->p_waited /* XXXSMP */)) { DPRINTF(("stat %d flag %d\n", t->p_stat, !t->p_waited)); return EBUSY; @@ -540,6 +545,7 @@ case PT_TRACE_ME: case PT_GET_SIGINFO: case PT_SET_SIGINFO: + case PT_STOP: return 1; default: return 0; @@ -891,7 +897,7 @@ #endif static int -ptrace_sendsig(struct proc *t, struct lwp *lt, int signo, int resume_all) +ptrace_sendsig(struct lwp *l, int req, struct proc *t, struct lwp *lt, int signo, int resume_all) { ksiginfo_t ksi; @@ -919,23 +925,20 @@ return 0; } - KSI_INIT_EMPTY(&ksi); - if (t->p_sigctx.ps_faked) { - if (signo != t->p_sigctx.ps_info._signo) - return EINVAL; - t->p_sigctx.ps_faked = false; - ksi.ksi_info = t->p_sigctx.ps_info; - ksi.ksi_lid = t->p_sigctx.ps_lwp; - } else if (signo == 0) { - return 0; - } else { - ksi.ksi_signo = signo; - } + KASSERT(req == PT_KILL || req == PT_STOP || req == PT_ATTACH); + + KSI_INIT(&ksi); + ksi.ksi_signo = signo; + ksi.ksi_code = SI_USER; + ksi.ksi_pid = l->l_proc->p_pid; + ksi.ksi_uid = kauth_cred_geteuid(l->l_cred); + + t->p_sigctx.ps_faked = false; + DPRINTF(("%s: pid=%d.%d signal=%d resume_all=%d\n", __func__, t->p_pid, - t->p_sigctx.ps_lwp, signo, resume_all)); + lt->l_lid, signo, resume_all)); - kpsignal2(t, &ksi); - return 0; + return kpsignal2(t, &ksi); } static int @@ -1328,7 +1331,7 @@ CLR(lt->l_pflag, LP_SINGLESTEP); } sendsig: - error = ptrace_sendsig(t, lt, signo, resume_all); + error = ptrace_sendsig(l, req, t, lt, signo, resume_all); break; case PT_SYSCALLEMU: @@ -1361,6 +1364,11 @@ signo = SIGKILL; goto sendsig; /* in PT_CONTINUE, above. */ + case PT_STOP: + /* just send the process a STOP signal. */ + signo = SIGSTOP; + goto sendsig; /* in PT_CONTINUE, above. */ + case PT_ATTACH: /* * Go ahead and set the trace flag. Index: sys/sys/ptrace.h =================================================================== RCS file: /cvsroot/src/sys/sys/ptrace.h,v retrieving revision 1.65 diff -u -r1.65 ptrace.h --- sys/sys/ptrace.h 11 Jun 2019 23:18:55 -0000 1.65 +++ sys/sys/ptrace.h 9 Oct 2019 12:53:30 -0000 @@ -57,6 +57,7 @@ #define PT_GET_SIGINFO 20 /* get signal state, defined below */ #define PT_RESUME 21 /* allow execution of the LWP */ #define PT_SUSPEND 22 /* prevent execution of the LWP */ +#define PT_STOP 23 /* stop the child process */ #define PT_FIRSTMACH 32 /* for machine-specific requests */ #include /* machine-specific requests, if any */