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;