Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Introduce new ptrace(2) operation PT_STOP



details:   https://anonhg.NetBSD.org/src/rev/925c0e947616
branches:  trunk
changeset: 455150:925c0e947616
user:      kamil <kamil%NetBSD.org@localhost>
date:      Wed Oct 09 13:19:43 2019 +0000

description:
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).

diffstat:

 sys/kern/sys_ptrace_common.c |  48 +++++++++++++++++++++++++------------------
 sys/sys/ptrace.h             |   3 +-
 2 files changed, 30 insertions(+), 21 deletions(-)

diffs (138 lines):

diff -r f28af4a00800 -r 925c0e947616 sys/kern/sys_ptrace_common.c
--- a/sys/kern/sys_ptrace_common.c      Wed Oct 09 13:13:08 2019 +0000
+++ b/sys/kern/sys_ptrace_common.c      Wed Oct 09 13:19:43 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sys_ptrace_common.c,v 1.65 2019/10/08 12:29:57 kamil Exp $     */
+/*     $NetBSD: sys_ptrace_common.c,v 1.66 2019/10/09 13:19:43 kamil 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.65 2019/10/08 12:29:57 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.66 2019/10/09 13:19:43 kamil Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ptrace.h"
@@ -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.
diff -r f28af4a00800 -r 925c0e947616 sys/sys/ptrace.h
--- a/sys/sys/ptrace.h  Wed Oct 09 13:13:08 2019 +0000
+++ b/sys/sys/ptrace.h  Wed Oct 09 13:19:43 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ptrace.h,v 1.65 2019/06/11 23:18:55 kamil Exp $        */
+/*     $NetBSD: ptrace.h,v 1.66 2019/10/09 13:19:43 kamil 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 */



Home | Main Index | Thread Index | Old Index