Module Name:    src
Committed By:   christos
Date:           Fri Sep  2 20:06:29 UTC 2011

Modified Files:
        src/sys/kern: kern_fork.c

Log Message:
Add support for PTRACE_FORK. NB: This does not (yet) work for vfork(), because:
1. When we vfork() PL_PPWAIT is set, and that makes us do regular disposition
   of the TRAP signal, and not indirect through the debugger.
2. The parent needs to keep running, so that the debugger can release it.
   Unfortunately, with vfork() we cannot release the parent because it will
   eventually core-dump since the parent and the child cannot run on the
   same address space.


To generate a diff of this commit:
cvs rdiff -u -r1.185 -r1.186 src/sys/kern/kern_fork.c

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.185 src/sys/kern/kern_fork.c:1.186
--- src/sys/kern/kern_fork.c:1.185	Tue Aug 23 09:01:25 2011
+++ src/sys/kern/kern_fork.c	Fri Sep  2 16:06:29 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_fork.c,v 1.185 2011/08/23 13:01:25 christos Exp $	*/
+/*	$NetBSD: kern_fork.c,v 1.186 2011/09/02 20:06:29 christos 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.185 2011/08/23 13:01:25 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.186 2011/09/02 20:06:29 christos Exp $");
 
 #include "opt_ktrace.h"
 
@@ -92,6 +92,7 @@
 #include <sys/syscallargs.h>
 #include <sys/uidinfo.h>
 #include <sys/sdt.h>
+#include <sys/ptrace.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -218,6 +219,7 @@
 	int		count;
 	vaddr_t		uaddr;
 	int		tnprocs;
+	int		tracefork;
 	int		error = 0;
 
 	p1 = l1->l_proc;
@@ -458,6 +460,35 @@
 	LIST_INSERT_HEAD(&parent->p_children, p2, p_sibling);
 	p2->p_exitsig = exitsig;		/* signal for parent on exit */
 
+	tracefork = (p1->p_slflag & (PSL_TRACEFORK|PSL_TRACED)) ==
+	    (PSL_TRACEFORK|PSL_TRACED);
+	if (tracefork) {
+		p2->p_slflag |= PSL_TRACED;
+		p2->p_opptr = p2->p_pptr;
+		if (p2->p_pptr != p1->p_pptr) {
+			struct proc *parent1 = p2->p_pptr;
+
+			if (parent1->p_lock < p2->p_lock) {
+				if (!mutex_tryenter(parent1->p_lock)) {
+					mutex_exit(p2->p_lock);
+					mutex_enter(parent1->p_lock);
+				}
+			} else if (parent1->p_lock > p2->p_lock) {
+				mutex_enter(parent1->p_lock);
+			}
+			parent1->p_slflag |= PSL_CHTRACED;
+			proc_reparent(p2, p1->p_pptr);
+			if (parent1->p_lock != p2->p_lock)
+				mutex_exit(parent1->p_lock);
+		}
+
+		/*
+		 * Set ptrace status.
+		 */
+		p1->p_fpid = p2->p_pid;
+		p2->p_fpid = p1->p_pid;
+	}
+
 	LIST_INSERT_AFTER(p1, p2, p_pglist);
 	LIST_INSERT_HEAD(&allproc, p2, p_list);
 
@@ -538,6 +569,17 @@
 	while (p2->p_lflag & PL_PPWAIT)
 		cv_wait(&p1->p_waitcv, proc_lock);
 
+        /*      
+         * Let the parent know that we are tracing its child.
+         */     
+	if (tracefork) {
+		ksiginfo_t ksi;
+                KSI_INIT_EMPTY(&ksi);
+                ksi.ksi_signo = SIGTRAP;
+                ksi.ksi_lid = l1->l_lid; 
+                kpsignal(p1, &ksi, NULL);
+	}
+
 	mutex_exit(proc_lock);
 
 	/*

Reply via email to