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 */

Reply via email to