Module Name:    src
Committed By:   kamil
Date:           Wed May  1 18:01:54 UTC 2019

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

Log Message:
Correct handling of corner cases in fork1(9) code under a debugger

Correct detaching and SIGKILLing forker and vforker in the middle of its
operation.


To generate a diff of this commit:
cvs rdiff -u -r1.210 -r1.211 src/sys/kern/kern_fork.c
cvs rdiff -u -r1.353 -r1.354 src/sys/kern/kern_sig.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.210 src/sys/kern/kern_fork.c:1.211
--- src/sys/kern/kern_fork.c:1.210	Wed May  1 17:21:55 2019
+++ src/sys/kern/kern_fork.c	Wed May  1 18:01:54 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_fork.c,v 1.210 2019/05/01 17:21:55 kamil Exp $	*/
+/*	$NetBSD: kern_fork.c,v 1.211 2019/05/01 18:01:54 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.210 2019/05/01 17:21:55 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.211 2019/05/01 18:01:54 kamil Exp $");
 
 #include "opt_ktrace.h"
 #include "opt_dtrace.h"
@@ -203,6 +203,30 @@ sys___clone(struct lwp *l, const struct 
  */
 static struct timeval fork_tfmrate = { 10, 0 };
 
+static inline bool
+tracefork(struct proc *p, int flags)
+{
+
+	return (p->p_slflag & (PSL_TRACEFORK|PSL_TRACED)) ==
+	    (PSL_TRACEFORK|PSL_TRACED) && (flags & FORK_PPWAIT) == 0;
+}
+
+static inline bool
+tracevfork(struct proc *p, int flags)
+{
+
+	return (p->p_slflag & (PSL_TRACEVFORK|PSL_TRACED)) ==
+	    (PSL_TRACEVFORK|PSL_TRACED) && (flags & FORK_PPWAIT) != 0;
+}
+
+static inline bool
+tracevforkdone(struct proc *p, int flags)
+{
+
+	return (p->p_slflag & (PSL_TRACEVFORK_DONE|PSL_TRACED)) ==
+	    (PSL_TRACEVFORK_DONE|PSL_TRACED) && (flags & FORK_PPWAIT);
+}
+
 /*
  * General fork call.  Note that another LWP in the process may call exec()
  * or exit() while we are forking.  It's safe to continue here, because
@@ -219,7 +243,7 @@ fork1(struct lwp *l1, int flags, int exi
 	int		count;
 	vaddr_t		uaddr;
 	int		tnprocs;
-	int		tracefork, tracevfork, tracevforkdone;
+	bool		trace_fork, trace_vfork;
 	int		error = 0;
 
 	p1 = l1->l_proc;
@@ -477,19 +501,15 @@ fork1(struct lwp *l1, int flags, int exi
 	/*
 	 * 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;
-	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 || tracevfork)
+	trace_fork = tracefork(p1, flags);
+	trace_vfork = tracevfork(p1, flags);
+	if (trace_fork || trace_vfork)
 		proc_changeparent(p2, p1->p_pptr);
-	if (tracefork) {
+	if (trace_fork) {
 		p1->p_fpid = p2->p_pid;
 		p2->p_fpid = p1->p_pid;
 	}
-	if (tracevfork) {
+	if (trace_vfork) {
 		p1->p_vfpid = p2->p_pid;
 		p2->p_vfpid = p1->p_pid;
 	}
@@ -573,7 +593,7 @@ fork1(struct lwp *l1, int flags, int exi
 	/*
 	 * Let the parent know that we are tracing its child.
 	 */
-	if (tracefork || tracevfork) {
+	if (tracefork(p1, flags) || tracevfork(p1, flags)) {
 		mutex_enter(p1->p_lock);
 		eventswitch(SIGTRAP, TRAP_CHLD);
 		// XXX ktrpoint(KTR_PSIG)
@@ -591,7 +611,7 @@ fork1(struct lwp *l1, int flags, int exi
 	/*
 	 * Let the parent know that we are tracing its child.
 	 */
-	if (tracevforkdone) {
+	if (tracevforkdone(p1, flags)) {
 		mutex_enter(p1->p_lock);
 		p1->p_vfpid_done = retval[0];
 		eventswitch(SIGTRAP, TRAP_CHLD);

Index: src/sys/kern/kern_sig.c
diff -u src/sys/kern/kern_sig.c:1.353 src/sys/kern/kern_sig.c:1.354
--- src/sys/kern/kern_sig.c:1.353	Wed May  1 17:21:55 2019
+++ src/sys/kern/kern_sig.c	Wed May  1 18:01:54 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_sig.c,v 1.353 2019/05/01 17:21:55 kamil Exp $	*/
+/*	$NetBSD: kern_sig.c,v 1.354 2019/05/01 18:01:54 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.353 2019/05/01 17:21:55 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.354 2019/05/01 18:01:54 kamil Exp $");
 
 #include "opt_ptrace.h"
 #include "opt_dtrace.h"
@@ -1544,6 +1544,15 @@ eventswitch(int signo, int code)
 	KASSERT(l->l_stat == LSONPROC);
 	KASSERT(p->p_nrlwps > 0);
 
+	/*
+	 * If there's a pending SIGKILL process it immediately.
+	 */
+	if (p->p_xsig == SIGKILL ||
+	    sigismember(&p->p_sigpend.sp_set, SIGKILL)) {
+		mutex_exit(proc_lock);
+		return;
+	}
+
 	p->p_xsig = signo;
 	p->p_sigctx.ps_faked = true;
 	p->p_sigctx.ps_info._signo = signo;

Reply via email to