Module Name:    src
Committed By:   kamil
Date:           Fri Jan 13 23:00:35 UTC 2017

Modified Files:
        src/sys/kern: kern_fork.c sys_ptrace_common.c
        src/sys/sys: proc.h ptrace.h

Log Message:
Add support for PTRACE_VFORK_DONE and stub for PTRACE_VFORK in ptrace(2)

PTRACE_VFORK is supposed to be used to track vfork(2)-like events, when
parent gives birth to new process child and stops till it exits or calls
exec().
Currently PTRACE_VFORK is a stub.

PTRACE_VFORK_DONE is notification to notify a debugger that a parent has
resumed after vfork(2)-like action.
PTRACE_VFORK_DONE throws SIGTRAP with TRAP_CHLD.

Sponsored by <The NetBSD Foundation>


To generate a diff of this commit:
cvs rdiff -u -r1.198 -r1.199 src/sys/kern/kern_fork.c
cvs rdiff -u -r1.8 -r1.9 src/sys/kern/sys_ptrace_common.c
cvs rdiff -u -r1.335 -r1.336 src/sys/sys/proc.h
cvs rdiff -u -r1.52 -r1.53 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/kern_fork.c
diff -u src/sys/kern/kern_fork.c:1.198 src/sys/kern/kern_fork.c:1.199
--- src/sys/kern/kern_fork.c:1.198	Tue Jan 10 00:48:37 2017
+++ src/sys/kern/kern_fork.c	Fri Jan 13 23:00:35 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_fork.c,v 1.198 2017/01/10 00:48:37 kamil Exp $	*/
+/*	$NetBSD: kern_fork.c,v 1.199 2017/01/13 23:00:35 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.198 2017/01/10 00:48:37 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.199 2017/01/13 23:00:35 kamil Exp $");
 
 #include "opt_ktrace.h"
 #include "opt_dtrace.h"
@@ -219,7 +219,7 @@ fork1(struct lwp *l1, int flags, int exi
 	int		count;
 	vaddr_t		uaddr;
 	int		tnprocs;
-	int		tracefork;
+	int		tracefork, tracevforkdone;
 	int		error = 0;
 
 	p1 = l1->l_proc;
@@ -471,11 +471,12 @@ fork1(struct lwp *l1, int flags, int exi
 	p2->p_exitsig = exitsig;		/* signal for parent on exit */
 
 	/*
-	 * We don't want to tracefork vfork()ed processes because they
-	 * will not receive the SIGTRAP until it is too late.
+	 * Trace fork(2) and vfork(2)-like events on demand in a debugger.
 	 */
 	tracefork = (p1->p_slflag & (PSL_TRACEFORK|PSL_TRACED)) ==
 	    (PSL_TRACEFORK|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) {
 		proc_changeparent(p2, p1->p_pptr);
 		/*
@@ -484,6 +485,12 @@ fork1(struct lwp *l1, int flags, int exi
 		p1->p_fpid = p2->p_pid;
 		p2->p_fpid = p1->p_pid;
 	}
+	if (tracevforkdone) {
+		/*
+		 * Set ptrace status.
+		 */
+		p1->p_vfpid_done = p2->p_pid;
+	}
 
 	LIST_INSERT_AFTER(p1, p2, p_pglist);
 	LIST_INSERT_HEAD(&allproc, p2, p_list);
@@ -576,7 +583,7 @@ fork1(struct lwp *l1, int flags, int exi
 	/*
 	 * Let the parent know that we are tracing its child.
 	 */
-	if (tracefork) {
+	if (tracefork || tracevforkdone) {
 		ksiginfo_t ksi;
 
 		KSI_INIT_EMPTY(&ksi);

Index: src/sys/kern/sys_ptrace_common.c
diff -u src/sys/kern/sys_ptrace_common.c:1.8 src/sys/kern/sys_ptrace_common.c:1.9
--- src/sys/kern/sys_ptrace_common.c:1.8	Fri Jan  6 22:53:17 2017
+++ src/sys/kern/sys_ptrace_common.c	Fri Jan 13 23:00:35 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_ptrace_common.c,v 1.8 2017/01/06 22:53:17 kamil Exp $	*/
+/*	$NetBSD: sys_ptrace_common.c,v 1.9 2017/01/13 23:00:35 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.8 2017/01/06 22:53:17 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.9 2017/01/13 23:00:35 kamil Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ptrace.h"
@@ -790,6 +790,8 @@ do_ptrace(struct ptrace_methods *ptm, st
 		}
 	sendsig:
 		t->p_fpid = 0;
+		t->p_vfpid = 0;
+		t->p_vfpid_done = 0;
 		/* Finally, deliver the requested signal (or none). */
 		if (t->p_stat == SSTOP) {
 			/*
@@ -855,6 +857,10 @@ do_ptrace(struct ptrace_methods *ptm, st
 		memset(&pe, 0, sizeof(pe));
 		pe.pe_set_event = ISSET(t->p_slflag, PSL_TRACEFORK) ?
 		    PTRACE_FORK : 0;
+		pe.pe_set_event |= ISSET(t->p_slflag, PSL_TRACEVFORK) ?
+		    PTRACE_VFORK : 0;
+		pe.pe_set_event |= ISSET(t->p_slflag, PSL_TRACEVFORK_DONE) ?
+		    PTRACE_VFORK_DONE : 0;
 		error = copyout(&pe, addr, sizeof(pe));
 		break;
 
@@ -871,6 +877,21 @@ do_ptrace(struct ptrace_methods *ptm, st
 			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) {
+			error = ENOTSUP;
+			break;
+		}
+#endif
+		if (pe.pe_set_event & PTRACE_VFORK_DONE)
+			SET(t->p_slflag, PSL_TRACEVFORK_DONE);
+		else
+			CLR(t->p_slflag, PSL_TRACEVFORK_DONE);
 		break;
 
 	case  PT_GET_PROCESS_STATE:
@@ -884,6 +905,12 @@ do_ptrace(struct ptrace_methods *ptm, st
 		if (t->p_fpid) {
 			ps.pe_report_event = PTRACE_FORK;
 			ps.pe_other_pid = t->p_fpid;
+		} else if (t->p_vfpid) {
+			ps.pe_report_event = PTRACE_VFORK;
+			ps.pe_other_pid = t->p_vfpid;
+		} else if (t->p_vfpid_done) {
+			ps.pe_report_event = PTRACE_VFORK_DONE;
+			ps.pe_other_pid = t->p_vfpid_done;
 		}
 		error = copyout(&ps, addr, sizeof(ps));
 		break;

Index: src/sys/sys/proc.h
diff -u src/sys/sys/proc.h:1.335 src/sys/sys/proc.h:1.336
--- src/sys/sys/proc.h:1.335	Wed Oct 19 09:44:01 2016
+++ src/sys/sys/proc.h	Fri Jan 13 23:00:35 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: proc.h,v 1.335 2016/10/19 09:44:01 skrll Exp $	*/
+/*	$NetBSD: proc.h,v 1.336 2017/01/13 23:00:35 kamil Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -310,6 +310,8 @@ struct proc {
 	struct lcproc	*p_lwpctl;	/* p, a: _lwp_ctl() information */
 	pid_t		p_ppid;		/* :: cached parent pid */
 	pid_t 		p_fpid;		/* :: forked pid */
+	pid_t 		p_vfpid;	/* :: vforked pid */
+	pid_t 		p_vfpid_done;	/* :: vforked done pid */
 	u_int		p_nsems;	/* Count of semaphores */
 
 /*
@@ -398,6 +400,9 @@ struct proc {
  * and p_lock.  Access from process context only.
  */
 #define	PSL_TRACEFORK	0x00000001 /* traced process wants fork events */
+#define	PSL_TRACEVFORK	0x00000002 /* traced process wants vfork events */
+#define	PSL_TRACEVFORK_DONE	\
+			0x00000004 /* traced process wants vfork done events */
 #define	PSL_TRACED	0x00000800 /* Debugged process being traced */
 #define	PSL_FSTRACE	0x00010000 /* Debugger process being traced by procfs */
 #define	PSL_CHTRACED	0x00400000 /* Child has been traced & reparented */

Index: src/sys/sys/ptrace.h
diff -u src/sys/sys/ptrace.h:1.52 src/sys/sys/ptrace.h:1.53
--- src/sys/sys/ptrace.h:1.52	Fri Jan  6 22:53:17 2017
+++ src/sys/sys/ptrace.h	Fri Jan 13 23:00:35 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: ptrace.h,v 1.52 2017/01/06 22:53:17 kamil Exp $	*/
+/*	$NetBSD: ptrace.h,v 1.53 2017/01/13 23:00:35 kamil Exp $	*/
 
 /*-
  * Copyright (c) 1984, 1993
@@ -93,7 +93,9 @@ typedef struct ptrace_state {
 	pid_t	pe_other_pid;
 } ptrace_state_t;
 
-#define	PTRACE_FORK	0x0001	/* Report forks */
+#define	PTRACE_FORK		0x0001	/* Report forks */
+#define	PTRACE_VFORK		0x0002	/* Report vforks */
+#define	PTRACE_VFORK_DONE	0x0004	/* Report parent resumed from vforks */
 
 /*
  * Argument structure for PT_IO.

Reply via email to