Module Name: src Committed By: martin Date: Tue Oct 15 19:11:02 UTC 2019
Modified Files: src/sys/kern [netbsd-9]: sys_ptrace_common.c src/sys/sys [netbsd-9]: ptrace.h Log Message: Pull up following revision(s) (requested by kamil in ticket #325): sys/sys/ptrace.h: revision 1.66 sys/kern/sys_ptrace_common.c: revision 1.66 Introduce new ptrace(2) operation PT_STOP It works like: - kill(SIGSTOP) for unstopped tracee - ptrace(PT_CONTINUE,SIGSTOP) for stopped tracee The child will be stopped and always possible to be waited (with wait(2) like calls). For stopped traccee kill(SIGSTOP) has no effect. PT_CONTINUE+SIGSTOP cannot be used on an unstopped process (EBUSY). This operation is modeled after PT_KILL that is similar for the SIGKILL call. While there, allow PT_KILL on unstopped traced child. This operation is useful in an abnormal exit of a debugger from a signal handler, usually followed by waitpid(2) and ptrace(PT_DETACH). To generate a diff of this commit: cvs rdiff -u -r1.58.2.7 -r1.58.2.8 src/sys/kern/sys_ptrace_common.c cvs rdiff -u -r1.65 -r1.65.2.1 src/sys/sys/ptrace.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/sys_ptrace_common.c diff -u src/sys/kern/sys_ptrace_common.c:1.58.2.7 src/sys/kern/sys_ptrace_common.c:1.58.2.8 --- src/sys/kern/sys_ptrace_common.c:1.58.2.7 Tue Oct 15 19:07:14 2019 +++ src/sys/kern/sys_ptrace_common.c Tue Oct 15 19:11:02 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: sys_ptrace_common.c,v 1.58.2.7 2019/10/15 19:07:14 martin Exp $ */ +/* $NetBSD: sys_ptrace_common.c,v 1.58.2.8 2019/10/15 19:11:02 martin Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -118,7 +118,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.58.2.7 2019/10/15 19:07:14 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.58.2.8 2019/10/15 19:11:02 martin Exp $"); #ifdef _KERNEL_OPT #include "opt_ptrace.h" @@ -286,6 +286,7 @@ ptrace_listener_cb(kauth_cred_t cred, ka case PT_DUMPCORE: case PT_RESUME: case PT_SUSPEND: + case PT_STOP: result = KAUTH_RESULT_ALLOW; break; @@ -493,6 +494,7 @@ ptrace_allowed(struct lwp *l, int req, s 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 @@ ptrace_allowed(struct lwp *l, int req, s /* * (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 @@ ptrace_needs_hold(int req) case PT_TRACE_ME: case PT_GET_SIGINFO: case PT_SET_SIGINFO: + case PT_STOP: return 1; default: return 0; @@ -891,7 +897,7 @@ ptrace_regs(struct lwp *l, struct lwp ** #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 @@ ptrace_sendsig(struct proc *t, struct lw 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 @@ -1332,7 +1335,7 @@ do_ptrace(struct ptrace_methods *ptm, st 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: @@ -1365,6 +1368,11 @@ do_ptrace(struct ptrace_methods *ptm, st 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: src/sys/sys/ptrace.h diff -u src/sys/sys/ptrace.h:1.65 src/sys/sys/ptrace.h:1.65.2.1 --- src/sys/sys/ptrace.h:1.65 Tue Jun 11 23:18:55 2019 +++ src/sys/sys/ptrace.h Tue Oct 15 19:11:02 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ptrace.h,v 1.65 2019/06/11 23:18:55 kamil Exp $ */ +/* $NetBSD: ptrace.h,v 1.65.2.1 2019/10/15 19:11:02 martin Exp $ */ /*- * Copyright (c) 1984, 1993 @@ -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/ptrace.h> /* machine-specific requests, if any */