summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libc/sys/ptrace.28
-rw-r--r--sys/kern/kern_fork.c44
-rw-r--r--sys/kern/kern_sig.c29
-rw-r--r--sys/kern/sys_ptrace_common.c13
-rw-r--r--sys/sys/signalvar.h4
-rw-r--r--tests/lib/libc/sys/t_ptrace_wait.c21
6 files changed, 65 insertions, 54 deletions
diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2
index 7e4bb2a700b..37e7c0932da 100644
--- a/lib/libc/sys/ptrace.2
+++ b/lib/libc/sys/ptrace.2
@@ -1,7 +1,7 @@
-.\" $NetBSD: ptrace.2,v 1.68 2018/03/05 11:24:35 kamil Exp $
+.\" $NetBSD: ptrace.2,v 1.69 2018/05/01 16:37:23 kamil Exp $
.\"
.\" This file is in the public domain.
-.Dd April 7, 2017
+.Dd May 1, 2018
.Dt PTRACE 2
.Os
.Sh NAME
@@ -841,10 +841,6 @@ to
.Ec ,
should be able to sidestep this.
.Pp
-.Dv PTRACE_VFORK
-is currently unimplemented and it will return
-.Er ENOTSUP .
-.Pp
.Dv PT_SET_SIGINFO ,
.Dv PT_RESUME
and
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 02b63231653..22cf730fa4a 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_fork.c,v 1.204 2018/04/16 14:51:59 kamil Exp $ */
+/* $NetBSD: kern_fork.c,v 1.205 2018/05/01 16:37:23 kamil Exp $ */
/*-
* Copyright (c) 1999, 2001, 2004, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.204 2018/04/16 14:51:59 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.205 2018/05/01 16:37:23 kamil Exp $");
#include "opt_ktrace.h"
#include "opt_dtrace.h"
@@ -218,7 +218,7 @@ fork1(struct lwp *l1, int flags, int exitsig, void *stack, size_t stacksize,
int count;
vaddr_t uaddr;
int tnprocs;
- int tracefork, tracevforkdone;
+ int tracefork, tracevfork, tracevforkdone;
int error = 0;
p1 = l1->l_proc;
@@ -478,21 +478,19 @@ fork1(struct lwp *l1, int flags, int exitsig, void *stack, size_t stacksize,
*/
tracefork = (p1->p_slflag & (PSL_TRACEFORK|PSL_TRACED)) ==
(PSL_TRACEFORK|PSL_TRACED) && (flags && FORK_PPWAIT) == 0;
+ tracevfork = (p1->p_slflag & (PSL_TRACEVFORK|PSL_TRACED)) ==
+ (PSL_TRACEVFORK|PSL_TRACED) && (flags && FORK_PPWAIT) != 0;
tracevforkdone = (p1->p_slflag & (PSL_TRACEVFORK_DONE|PSL_TRACED)) ==
(PSL_TRACEVFORK_DONE|PSL_TRACED) && (flags && FORK_PPWAIT);
- if (tracefork) {
+ if (tracefork || tracevfork)
proc_changeparent(p2, p1->p_pptr);
- /*
- * Set ptrace status.
- */
+ if (tracefork) {
p1->p_fpid = p2->p_pid;
p2->p_fpid = p1->p_pid;
}
- if (tracevforkdone) {
- /*
- * Set ptrace status.
- */
- p1->p_vfpid_done = p2->p_pid;
+ if (tracevfork) {
+ p1->p_vfpid = p2->p_pid;
+ p2->p_vfpid = p1->p_pid;
}
LIST_INSERT_AFTER(p1, p2, p_pglist);
@@ -579,19 +577,35 @@ fork1(struct lwp *l1, int flags, int exitsig, void *stack, size_t stacksize,
retval[0] = p2->p_pid;
retval[1] = 0;
}
+
mutex_exit(p2->p_lock);
/*
+ * Let the parent know that we are tracing its child.
+ */
+ if (tracefork || tracevfork) {
+ mutex_enter(p1->p_lock);
+ p1->p_xsig = SIGTRAP;
+ p1->p_sigctx.ps_faked = true; // XXX
+ p1->p_sigctx.ps_info._signo = p1->p_xsig;
+ p1->p_sigctx.ps_info._code = TRAP_CHLD;
+ sigswitch(0, SIGTRAP, false);
+ // XXX ktrpoint(KTR_PSIG)
+ mutex_exit(p1->p_lock);
+ mutex_enter(proc_lock);
+ }
+
+ /*
* Preserve synchronization semantics of vfork. If waiting for
* child to exec or exit, sleep until it clears LP_VFORKWAIT.
*/
- while (p2->p_lflag & PL_PPWAIT)
+ while (p2->p_lflag & PL_PPWAIT) // XXX: p2 can go invalid
cv_wait(&p1->p_waitcv, proc_lock);
/*
* Let the parent know that we are tracing its child.
*/
- if (tracefork || tracevforkdone) {
+ if (tracevforkdone) {
ksiginfo_t ksi;
KSI_INIT_EMPTY(&ksi);
@@ -599,6 +613,8 @@ fork1(struct lwp *l1, int flags, int exitsig, void *stack, size_t stacksize,
ksi.ksi_code = TRAP_CHLD;
ksi.ksi_lid = l1->l_lid;
kpsignal(p1, &ksi, NULL);
+
+ p1->p_vfpid_done = retval[0];
}
mutex_exit(proc_lock);
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index a713893e1c9..6111f7e0b25 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_sig.c,v 1.341 2018/05/01 13:48:38 kamil Exp $ */
+/* $NetBSD: kern_sig.c,v 1.342 2018/05/01 16:37:23 kamil Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.341 2018/05/01 13:48:38 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.342 2018/05/01 16:37:23 kamil Exp $");
#include "opt_ptrace.h"
#include "opt_dtrace.h"
@@ -118,12 +118,12 @@ sigset_t sigcantmask __cacheline_aligned;
static void ksiginfo_exechook(struct proc *, void *);
static void proc_stop(struct proc *, int);
+static void proc_stop_done(struct proc *, int);
static void proc_stop_callout(void *);
static int sigchecktrace(void);
static int sigpost(struct lwp *, sig_t, int, int);
static int sigput(sigpend_t *, struct proc *, ksiginfo_t *);
static int sigunwait(struct proc *, const ksiginfo_t *);
-static void sigswitch(int, int);
static void sigacts_poolpage_free(struct pool *, void *);
static void *sigacts_poolpage_alloc(struct pool *, int);
@@ -1528,8 +1528,8 @@ proc_stop_done(struct proc *p, int ppmask)
/*
* Stop the current process and switch away when being stopped or traced.
*/
-static void
-sigswitch(int ppmask, int signo)
+void
+sigswitch(int ppmask, int signo, bool relock)
{
struct lwp *l = curlwp;
struct proc *p = l->l_proc;
@@ -1555,7 +1555,7 @@ sigswitch(int ppmask, int signo)
* a new signal, then signal the parent.
*/
if ((p->p_sflag & PS_STOPPING) != 0) {
- if (!mutex_tryenter(proc_lock)) {
+ if (relock && !mutex_tryenter(proc_lock)) {
mutex_exit(p->p_lock);
mutex_enter(proc_lock);
mutex_enter(p->p_lock);
@@ -1665,7 +1665,7 @@ issignal(struct lwp *l)
* we awaken, check for a signal from the debugger.
*/
if (p->p_stat == SSTOP || (p->p_sflag & PS_STOPPING) != 0) {
- sigswitch(PS_NOCLDSTOP, 0);
+ sigswitch(PS_NOCLDSTOP, 0, true);
signo = sigchecktrace();
} else
signo = 0;
@@ -1718,11 +1718,12 @@ issignal(struct lwp *l)
/*
* If traced, always stop, and stay stopped until released
- * by the debugger. If the our parent process is waiting
- * for us, don't hang as we could deadlock.
+ * by the debugger. If the our parent is our debugger waiting
+ * for us and we vforked, don't hang as we could deadlock.
+ *
+ * XXX: support PT_TRACE_ME called after vfork(2)
*/
- if ((p->p_slflag & PSL_TRACED) != 0 &&
- (p->p_lflag & PL_PPWAIT) == 0 && signo != SIGKILL) {
+ if ((p->p_slflag & PSL_TRACED) != 0 && signo != SIGKILL) {
/*
* Take the signal, but don't remove it from the
* siginfo queue, because the debugger can send
@@ -1735,7 +1736,7 @@ issignal(struct lwp *l)
/* Emulation-specific handling of signal trace */
if (p->p_emul->e_tracesig == NULL ||
(*p->p_emul->e_tracesig)(p, signo) == 0)
- sigswitch(0, signo);
+ sigswitch(0, signo, true);
/* Check for a signal from the debugger. */
if ((signo = sigchecktrace()) == 0)
@@ -1789,7 +1790,7 @@ issignal(struct lwp *l)
p->p_xsig = signo;
p->p_sflag &= ~PS_CONTINUED;
signo = 0;
- sigswitch(PS_NOCLDSTOP, p->p_xsig);
+ sigswitch(PS_NOCLDSTOP, p->p_xsig, true);
} else if (prop & SA_IGNORE) {
/*
* Except for SIGCONT, shouldn't get here.
@@ -2298,7 +2299,7 @@ proc_stoptrace(int trapno)
p->p_xsig = signo;
p->p_sigctx.ps_lwp = ksi.ksi_lid;
p->p_sigctx.ps_info = ksi.ksi_info;
- sigswitch(0, signo);
+ sigswitch(0, signo, true);
mutex_exit(p->p_lock);
if (ktrpoint(KTR_PSIG)) {
diff --git a/sys/kern/sys_ptrace_common.c b/sys/kern/sys_ptrace_common.c
index 4e483d846fd..ca2078ae146 100644
--- a/sys/kern/sys_ptrace_common.c
+++ b/sys/kern/sys_ptrace_common.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_ptrace_common.c,v 1.39 2018/05/01 14:09:53 kamil Exp $ */
+/* $NetBSD: sys_ptrace_common.c,v 1.40 2018/05/01 16:37:23 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.39 2018/05/01 14:09:53 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.40 2018/05/01 16:37:23 kamil Exp $");
#ifdef _KERNEL_OPT
#include "opt_ptrace.h"
@@ -634,23 +634,22 @@ ptrace_set_event_mask(struct proc *t, void *addr, size_t data)
SET(t->p_slflag, PSL_TRACEFORK);
else
CLR(t->p_slflag, PSL_TRACEFORK);
-#if notyet
+
if (pe.pe_set_event & PTRACE_VFORK)
SET(t->p_slflag, PSL_TRACEVFORK);
else
CLR(t->p_slflag, PSL_TRACEVFORK);
-#else
- if (pe.pe_set_event & PTRACE_VFORK)
- return ENOTSUP;
-#endif
+
if (pe.pe_set_event & PTRACE_VFORK_DONE)
SET(t->p_slflag, PSL_TRACEVFORK_DONE);
else
CLR(t->p_slflag, PSL_TRACEVFORK_DONE);
+
if (pe.pe_set_event & PTRACE_LWP_CREATE)
SET(t->p_slflag, PSL_TRACELWP_CREATE);
else
CLR(t->p_slflag, PSL_TRACELWP_CREATE);
+
if (pe.pe_set_event & PTRACE_LWP_EXIT)
SET(t->p_slflag, PSL_TRACELWP_EXIT);
else
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index 912409a37e8..dea1eb94a47 100644
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: signalvar.h,v 1.89 2018/04/19 21:19:07 christos Exp $ */
+/* $NetBSD: signalvar.h,v 1.90 2018/05/01 16:37:23 kamil Exp $ */
/*
* Copyright (c) 1991, 1993
@@ -136,6 +136,8 @@ void killproc(struct proc *, const char *);
void setsigvec(struct proc *, int, struct sigaction *);
int killpg1(struct lwp *, struct ksiginfo *, int, int);
void proc_unstop(struct proc *p);
+void sigswitch(int, int, bool);
+
int sigaction1(struct lwp *, int, const struct sigaction *,
struct sigaction *, const void *, int);
diff --git a/tests/lib/libc/sys/t_ptrace_wait.c b/tests/lib/libc/sys/t_ptrace_wait.c
index 14440e0c6ec..d214760ec15 100644
--- a/tests/lib/libc/sys/t_ptrace_wait.c
+++ b/tests/lib/libc/sys/t_ptrace_wait.c
@@ -1,4 +1,4 @@
-/* $NetBSD: t_ptrace_wait.c,v 1.37 2018/04/29 13:56:00 kamil Exp $ */
+/* $NetBSD: t_ptrace_wait.c,v 1.38 2018/05/01 16:37:23 kamil Exp $ */
/*-
* Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: t_ptrace_wait.c,v 1.37 2018/04/29 13:56:00 kamil Exp $");
+__RCSID("$NetBSD: t_ptrace_wait.c,v 1.38 2018/05/01 16:37:23 kamil Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -1189,8 +1189,6 @@ ATF_TC_BODY(eventmask3, tc)
ptrace_event_t set_event, get_event;
const int len = sizeof(ptrace_event_t);
- atf_tc_expect_fail("PR kern/51630");
-
DPRINTF("Before forking process PID=%d\n", getpid());
SYSCALL_REQUIRE((child = fork()) != -1);
if (child == 0) {
@@ -1211,7 +1209,7 @@ ATF_TC_BODY(eventmask3, tc)
validate_status_stopped(status, sigval);
set_event.pe_set_event = PTRACE_VFORK;
- SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1 || errno == ENOTSUP);
+ SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1);
SYSCALL_REQUIRE(ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1);
ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0);
@@ -1409,10 +1407,6 @@ fork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork,
ptrace_event_t event;
const int elen = sizeof(event);
- if (trackvfork) {
- atf_tc_expect_fail("PR kern/51630");
- }
-
DPRINTF("Before forking process PID=%d\n", getpid());
SYSCALL_REQUIRE((child = fork()) != -1);
if (child == 0) {
@@ -5722,7 +5716,7 @@ ATF_TC_BODY(signal6, tc)
ptrace_event_t event;
const int elen = sizeof(event);
- atf_tc_expect_timeout("PR kern/51918");
+ atf_tc_expect_fail("PR kern/51918");
DPRINTF("Before forking process PID=%d\n", getpid());
SYSCALL_REQUIRE((child = fork()) != -1);
@@ -5853,7 +5847,7 @@ ATF_TC_BODY(signal7, tc)
ptrace_event_t event;
const int elen = sizeof(event);
- atf_tc_expect_fail("PR kern/51918 PR kern/51630");
+ atf_tc_expect_fail("PR kern/51918");
DPRINTF("Before forking process PID=%d\n", getpid());
SYSCALL_REQUIRE((child = fork()) != -1);
@@ -6676,6 +6670,8 @@ ATF_TC_BODY(syscall1, tc)
DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
+ DPRINTF("Before checking siginfo_t and lwpid\n");
+ ATF_REQUIRE_EQ(info.psi_lwpid, 1);
ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE);
@@ -6691,7 +6687,8 @@ ATF_TC_BODY(syscall1, tc)
DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
- DPRINTF("Before checking siginfo_t\n");
+ DPRINTF("Before checking siginfo_t and lwpid\n");
+ ATF_REQUIRE_EQ(info.psi_lwpid, 1);
ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX);