Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/sys Introduce new ptrace(2) operations: PT_SET_SIGPASS a...
details: https://anonhg.NetBSD.org/src/rev/92299a4265bc
branches: trunk
changeset: 932712:92299a4265bc
user: kamil <kamil%NetBSD.org@localhost>
date: Thu May 14 13:32:15 2020 +0000
description:
Introduce new ptrace(2) operations: PT_SET_SIGPASS and PT_GET_SIGPASS
They deliver the logic of bypassing selected signals directly to the
debuggee, without informing the debugger.
This can be used to implement the QPassSignals GDB/LLDB protocol.
This call can be useful to avoid signal races in ATF ptrace tests.
diffstat:
lib/libc/sys/ptrace.2 | 29 +++++++++++++++++++-
sys/kern/kern_sig.c | 30 +++++++++++++--------
sys/kern/sys_ptrace_common.c | 60 ++++++++++++++++++++++++++++++++++++++++++-
sys/sys/ptrace.h | 8 ++++-
sys/sys/signalvar.h | 3 +-
5 files changed, 111 insertions(+), 19 deletions(-)
diffs (truncated from 332 to 300 lines):
diff -r d5b2926ed966 -r 92299a4265bc lib/libc/sys/ptrace.2
--- a/lib/libc/sys/ptrace.2 Thu May 14 13:25:40 2020 +0000
+++ b/lib/libc/sys/ptrace.2 Thu May 14 13:32:15 2020 +0000
@@ -1,7 +1,7 @@
-.\" $NetBSD: ptrace.2,v 1.83 2020/01/04 04:40:17 kamil Exp $
+.\" $NetBSD: ptrace.2,v 1.84 2020/05/14 13:32:15 kamil Exp $
.\"
.\" This file is in the public domain.
-.Dd January 4, 2019
+.Dd May 14, 2020
.Dt PTRACE 2
.Os
.Sh NAME
@@ -623,6 +623,31 @@
.Fa data
argument should be set to
.Li sizeof(struct ptrace_siginfo) .
+.It Dv PT_SET_SIGPASS
+This request can be used to specify mask of signals that should be passed
+directly to the debuggee, without reporting to the tracer.
+A pointer to sigset_t is passed in
+.Fa addr .
+The
+.Fa data
+argument should be set to
+.Li sizeof(sigset_t) .
+.Pp
+It is not permitted to mask SIGSTOP and SIGKILL.
+All debugger related signals
+(SIGTRAP, SIGILL, SIGSEGV, SIGBUS, SIGFPE)
+are reported to the tracer without interruption,
+unless they were emitted by a non-crash source.
+.It Dv PT_GET_SIGPASS
+This request can be used to determine mask of signals passed directly to the debuggee.
+A pointer to sigset_t is passed in
+.Fa addr .
+The
+.Fa data
+argument should be set to
+.Li sizeof(sigset_t) .
+.Pp
+Upon debugger attach the sigpass mask shall be empty.
.It Dv PT_RESUME
Allow execution of a specified thread,
change its state from suspended to continued.
diff -r d5b2926ed966 -r 92299a4265bc sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c Thu May 14 13:25:40 2020 +0000
+++ b/sys/kern/kern_sig.c Thu May 14 13:32:15 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_sig.c,v 1.388 2020/05/07 20:02:34 kamil Exp $ */
+/* $NetBSD: kern_sig.c,v 1.389 2020/05/14 13:32:15 kamil Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008, 2019 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.388 2020/05/07 20:02:34 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.389 2020/05/14 13:32:15 kamil Exp $");
#include "opt_ptrace.h"
#include "opt_dtrace.h"
@@ -1302,6 +1302,7 @@
lwpid_t lid;
sig_t action;
bool toall;
+ bool traced;
int error = 0;
KASSERT(!cpu_intr_p());
@@ -1329,11 +1330,13 @@
prop = sigprop[signo];
toall = ((prop & SA_TOALL) != 0);
lid = toall ? 0 : ksi->ksi_lid;
+ traced = ISSET(p->p_slflag, PSL_TRACED) &&
+ !sigismember(&p->p_sigctx.ps_sigpass, signo);
/*
* If proc is traced, always give parent a chance.
*/
- if (p->p_slflag & PSL_TRACED) {
+ if (traced) {
action = SIG_DFL;
if (lid == 0) {
@@ -1428,7 +1431,7 @@
* or for an SA process.
*/
if (p->p_stat == SACTIVE && (p->p_sflag & PS_STOPPING) == 0) {
- if ((p->p_slflag & PSL_TRACED) != 0)
+ if (traced)
goto deliver;
/*
@@ -1444,7 +1447,7 @@
* - If traced, then no action is needed, unless killing.
* - Run the process only if sending SIGCONT or SIGKILL.
*/
- if ((p->p_slflag & PSL_TRACED) != 0 && signo != SIGKILL) {
+ if (traced && signo != SIGKILL) {
goto out;
}
if ((prop & SA_CONT) != 0 || signo == SIGKILL) {
@@ -1456,7 +1459,7 @@
p->p_pptr->p_nstopchild--;
p->p_stat = SACTIVE;
p->p_sflag &= ~PS_STOPPING;
- if (p->p_slflag & PSL_TRACED) {
+ if (traced) {
KASSERT(signo == SIGKILL);
goto deliver;
}
@@ -1487,7 +1490,7 @@
/*
* Make signal pending.
*/
- KASSERT((p->p_slflag & PSL_TRACED) == 0);
+ KASSERT(!traced);
if ((error = sigput(&p->p_sigpend, p, kp)) != 0)
goto out;
deliver:
@@ -1844,6 +1847,7 @@
int siglwp, signo, prop;
sigpend_t *sp;
sigset_t ss;
+ bool traced;
p = l->l_proc;
sp = NULL;
@@ -1910,6 +1914,9 @@
}
}
+ traced = ISSET(p->p_slflag, PSL_TRACED) &&
+ !sigismember(&p->p_sigctx.ps_sigpass, signo);
+
if (sp) {
/* Overwrite process' signal context to correspond
* to the currently reported LWP. This is necessary
@@ -1937,7 +1944,7 @@
* we are being traced.
*/
if (sigismember(&p->p_sigctx.ps_sigignore, signo) &&
- (p->p_slflag & PSL_TRACED) == 0) {
+ !traced) {
/* Discard the signal. */
continue;
}
@@ -1947,7 +1954,7 @@
* by the debugger. If the our parent is our debugger waiting
* for us and we vforked, don't hang as we could deadlock.
*/
- if (ISSET(p->p_slflag, PSL_TRACED) && signo != SIGKILL &&
+ if (traced && signo != SIGKILL &&
!(ISSET(p->p_lflag, PL_PPWAIT) &&
(p->p_pptr == p->p_opptr))) {
/*
@@ -2004,7 +2011,7 @@
* XXX Don't hold proc_lock for p_lflag,
* but it's not a big deal.
*/
- if ((ISSET(p->p_slflag, PSL_TRACED) &&
+ if ((traced &&
!(ISSET(p->p_lflag, PL_PPWAIT) &&
(p->p_pptr == p->p_opptr))) ||
((p->p_lflag & PL_ORPHANPG) != 0 &&
@@ -2035,8 +2042,7 @@
* to take action on an ignored signal other
* than SIGCONT, unless process is traced.
*/
- if ((prop & SA_CONT) == 0 &&
- (p->p_slflag & PSL_TRACED) == 0)
+ if ((prop & SA_CONT) == 0 && !traced)
printf_nolog("issignal\n");
#endif
continue;
diff -r d5b2926ed966 -r 92299a4265bc sys/kern/sys_ptrace_common.c
--- a/sys/kern/sys_ptrace_common.c Thu May 14 13:25:40 2020 +0000
+++ b/sys/kern/sys_ptrace_common.c Thu May 14 13:32:15 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_ptrace_common.c,v 1.79 2020/05/08 10:35:51 kamil Exp $ */
+/* $NetBSD: sys_ptrace_common.c,v 1.80 2020/05/14 13:32:15 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.79 2020/05/08 10:35:51 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.80 2020/05/14 13:32:15 kamil Exp $");
#ifdef _KERNEL_OPT
#include "opt_ptrace.h"
@@ -290,6 +290,8 @@
case PT_STOP:
case PT_LWPSTATUS:
case PT_LWPNEXT:
+ case PT_SET_SIGPASS:
+ case PT_GET_SIGPASS:
result = KAUTH_RESULT_ALLOW;
break;
@@ -500,6 +502,8 @@
case PT_STOP:
case PT_LWPSTATUS:
case PT_LWPNEXT:
+ case PT_SET_SIGPASS:
+ case PT_GET_SIGPASS:
/*
* You can't do what you want to the process if:
* (1) It's not being traced at all,
@@ -622,6 +626,47 @@
}
static int
+ptrace_get_sigpass(struct proc *t, void *addr, size_t data)
+{
+ sigset_t set;
+
+ if (data > sizeof(set) || data <= 0) {
+ DPRINTF(("%s: invalid data: %zu < %zu <= 0\n",
+ __func__, sizeof(set), data));
+ return EINVAL;
+ }
+
+ set = t->p_sigctx.ps_sigpass;
+
+ return copyout(&set, addr, data);
+}
+
+static int
+ptrace_set_sigpass(struct proc *t, void *addr, size_t data)
+{
+ sigset_t set;
+ int error;
+
+ if (data > sizeof(set) || data <= 0) {
+ DPRINTF(("%s: invalid data: %zu < %zu <= 0\n",
+ __func__, sizeof(set), data));
+ return EINVAL;
+ }
+
+ memset(&set, 0, sizeof(set));
+
+ if ((error = copyin(addr, &set, data)))
+ return error;
+
+ /* We catch SIGSTOP and cannot intercept SIGKILL. */
+ sigminusset(&sigcantmask, &set);
+
+ t->p_sigctx.ps_sigpass = set;
+
+ return 0;
+}
+
+static int
ptrace_get_event_mask(struct proc *t, void *addr, size_t data)
{
struct ptrace_event pe;
@@ -1395,6 +1440,9 @@
CLR(t->p_slflag,
PSL_TRACED|PSL_TRACEDCHILD|PSL_SYSCALL);
+ /* clear sigpass mask */
+ sigemptyset(&t->p_sigctx.ps_sigpass);
+
/* give process back to original parent or init */
if (t->p_opptr != t->p_pptr) {
struct proc *pp = t->p_opptr;
@@ -1499,6 +1547,14 @@
error = ptrace_lwpstatus(t, ptm, <, addr, data, true);
break;
+ case PT_SET_SIGPASS:
+ error = ptrace_set_sigpass(t, addr, data);
+ break;
+
+ case PT_GET_SIGPASS:
+ error = ptrace_get_sigpass(t, addr, data);
+ break;
+
#ifdef PT_REGISTERS
case_PT_SETREGS
case_PT_GETREGS
diff -r d5b2926ed966 -r 92299a4265bc sys/sys/ptrace.h
--- a/sys/sys/ptrace.h Thu May 14 13:25:40 2020 +0000
+++ b/sys/sys/ptrace.h Thu May 14 13:32:15 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ptrace.h,v 1.69 2019/12/26 08:52:38 kamil Exp $ */
+/* $NetBSD: ptrace.h,v 1.70 2020/05/14 13:32:15 kamil Exp $ */
/*-
* Copyright (c) 1984, 1993
@@ -63,6 +63,8 @@
#define PT_STOP 23 /* stop the child process */
#define PT_LWPSTATUS 24 /* get info about the LWP */
#define PT_LWPNEXT 25 /* get info about next LWP */
+#define PT_SET_SIGPASS 26 /* set signals to pass to debuggee */
Home |
Main Index |
Thread Index |
Old Index