Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern Correct handling of corner cases in fork1(9) code u...



details:   https://anonhg.NetBSD.org/src/rev/8de6f25d5853
branches:  trunk
changeset: 450974:8de6f25d5853
user:      kamil <kamil%NetBSD.org@localhost>
date:      Wed May 01 18:01:54 2019 +0000

description:
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.

diffstat:

 sys/kern/kern_fork.c |  48 ++++++++++++++++++++++++++++++++++--------------
 sys/kern/kern_sig.c  |  13 +++++++++++--
 2 files changed, 45 insertions(+), 16 deletions(-)

diffs (135 lines):

diff -r 5833119328bc -r 8de6f25d5853 sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c      Wed May 01 17:21:55 2019 +0000
+++ b/sys/kern/kern_fork.c      Wed May 01 18:01:54 2019 +0000
@@ -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 @@
  */
 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 @@
        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 @@
        /*
         * 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 @@
        /*
         * 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 @@
        /*
         * 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);
diff -r 5833119328bc -r 8de6f25d5853 sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c       Wed May 01 17:21:55 2019 +0000
+++ b/sys/kern/kern_sig.c       Wed May 01 18:01:54 2019 +0000
@@ -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 @@
        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;



Home | Main Index | Thread Index | Old Index