Module Name: src Committed By: christos Date: Thu Mar 23 21:59:55 UTC 2017
Modified Files: src/sys/kern: kern_sig.c kern_syscall.c sys_process.c src/sys/sys: ptrace.h Log Message: kern/5201{2,8,9}: Fix PT_SYSCALL stopping. 1. Supply the siginfo we expect TRAP_SC{E,X} to process_stoptrace() and set it. 2. Change the second argument of proc_stop from notify, to now meaning that we want to stop right now. Wait in process_stoptrace until that has happened. 3. While here, fix the locking order in process_stoptrace(). To generate a diff of this commit: cvs rdiff -u -r1.332 -r1.333 src/sys/kern/kern_sig.c cvs rdiff -u -r1.14 -r1.15 src/sys/kern/kern_syscall.c cvs rdiff -u -r1.176 -r1.177 src/sys/kern/sys_process.c cvs rdiff -u -r1.58 -r1.59 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_sig.c diff -u src/sys/kern/kern_sig.c:1.332 src/sys/kern/kern_sig.c:1.333 --- src/sys/kern/kern_sig.c:1.332 Fri Jan 6 17:53:17 2017 +++ src/sys/kern/kern_sig.c Thu Mar 23 17:59:55 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_sig.c,v 1.332 2017/01/06 22:53:17 kamil Exp $ */ +/* $NetBSD: kern_sig.c,v 1.333 2017/03/23 21:59:55 christos 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.332 2017/01/06 22:53:17 kamil Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.333 2017/03/23 21:59:55 christos Exp $"); #include "opt_ptrace.h" #include "opt_dtrace.h" @@ -1535,7 +1535,7 @@ sigswitch(bool ppsig, int ppmask, int si */ if (p->p_stat == SACTIVE && (p->p_sflag & PS_STOPPING) == 0) { KASSERT(signo != 0); - proc_stop(p, 1, signo); + proc_stop(p, 0, signo); KASSERT(p->p_nrlwps > 0); } @@ -2099,7 +2099,7 @@ sigexit(struct lwp *l, int signo) * Put process 'p' into the stopped state and optionally, notify the parent. */ void -proc_stop(struct proc *p, int notify, int signo) +proc_stop(struct proc *p, int now, int signo) { struct lwp *l; @@ -2110,11 +2110,7 @@ proc_stop(struct proc *p, int notify, in * LWPs to a halt so they are included in p->p_nrlwps. We musn't * unlock between here and the p->p_nrlwps check below. */ - p->p_sflag |= PS_STOPPING; - if (notify) - p->p_sflag |= PS_NOTIFYSTOP; - else - p->p_sflag &= ~PS_NOTIFYSTOP; + p->p_sflag |= PS_STOPPING | PS_NOTIFYSTOP; membar_producer(); proc_stop_lwps(p); @@ -2125,7 +2121,7 @@ proc_stop(struct proc *p, int notify, in * LWP to stop will take care of it. */ - if (p->p_nrlwps == 0) { + if (p->p_nrlwps == 0 || (now && p->p_nrlwps == 1 && p == curproc)) { proc_stop_done(p, true, PS_NOCLDSTOP); } else { /* Index: src/sys/kern/kern_syscall.c diff -u src/sys/kern/kern_syscall.c:1.14 src/sys/kern/kern_syscall.c:1.15 --- src/sys/kern/kern_syscall.c:1.14 Mon Nov 30 18:34:47 2015 +++ src/sys/kern/kern_syscall.c Thu Mar 23 17:59:55 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_syscall.c,v 1.14 2015/11/30 23:34:47 pgoyette Exp $ */ +/* $NetBSD: kern_syscall.c,v 1.15 2017/03/23 21:59:55 christos Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_syscall.c,v 1.14 2015/11/30 23:34:47 pgoyette Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_syscall.c,v 1.15 2017/03/23 21:59:55 christos Exp $"); #ifdef _KERNEL_OPT #include "opt_modular.h" @@ -248,7 +248,7 @@ trace_enter(register_t code, const struc #ifdef PTRACE if ((curlwp->l_proc->p_slflag & (PSL_SYSCALL|PSL_TRACED)) == (PSL_SYSCALL|PSL_TRACED)) { - process_stoptrace(); + process_stoptrace(TRAP_SCE); if (curlwp->l_proc->p_slflag & PSL_SYSCALLEMU) { /* tracer will emulate syscall for us */ error = EJUSTRETURN; @@ -288,8 +288,9 @@ trace_exit(register_t code, const struct #ifdef PTRACE if ((p->p_slflag & (PSL_SYSCALL|PSL_TRACED|PSL_SYSCALLEMU)) == - (PSL_SYSCALL|PSL_TRACED)) - process_stoptrace(); + (PSL_SYSCALL|PSL_TRACED)) { + process_stoptrace(TRAP_SCX); + } CLR(p->p_slflag, PSL_SYSCALLEMU); #endif } Index: src/sys/kern/sys_process.c diff -u src/sys/kern/sys_process.c:1.176 src/sys/kern/sys_process.c:1.177 --- src/sys/kern/sys_process.c:1.176 Wed Mar 22 18:11:47 2017 +++ src/sys/kern/sys_process.c Thu Mar 23 17:59:55 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sys_process.c,v 1.176 2017/03/22 22:11:47 skrll Exp $ */ +/* $NetBSD: sys_process.c,v 1.177 2017/03/23 21:59:55 christos Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -118,7 +118,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.176 2017/03/22 22:11:47 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.177 2017/03/23 21:59:55 christos Exp $"); #ifdef _KERNEL_OPT #include "opt_ptrace.h" @@ -187,13 +187,13 @@ process_domem(struct lwp *curl /*tracer* } void -process_stoptrace(void) +process_stoptrace(int trapno) { struct lwp *l = curlwp; struct proc *p = l->l_proc, *pp; - mutex_enter(proc_lock); mutex_enter(p->p_lock); + mutex_enter(proc_lock); pp = p->p_pptr; if (pp->p_pid == 1) { CLR(p->p_slflag, PSL_SYSCALL); /* XXXSMP */ @@ -202,6 +202,8 @@ process_stoptrace(void) return; } + p->p_sigctx.ps_info._signo = SIGTRAP; + p->p_sigctx.ps_info._code = trapno; p->p_xsig = SIGTRAP; proc_stop(p, 1, SIGSTOP); mutex_exit(proc_lock); @@ -211,6 +213,14 @@ process_stoptrace(void) l->l_flag |= LW_PENDSIG; lwp_unlock(l); } + /* Switch and wait until we come to a stop */ + do { + mutex_exit(p->p_lock); + lwp_lock(l); + mi_switch(l); + mutex_enter(p->p_lock); + } while (p->p_sflag & PS_STOPPING); + mutex_exit(p->p_lock); } #endif /* KTRACE || PTRACE_HOOKS */ Index: src/sys/sys/ptrace.h diff -u src/sys/sys/ptrace.h:1.58 src/sys/sys/ptrace.h:1.59 --- src/sys/sys/ptrace.h:1.58 Wed Feb 22 22:34:23 2017 +++ src/sys/sys/ptrace.h Thu Mar 23 17:59:54 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ptrace.h,v 1.58 2017/02/23 03:34:23 kamil Exp $ */ +/* $NetBSD: ptrace.h,v 1.59 2017/03/23 21:59:54 christos Exp $ */ /*- * Copyright (c) 1984, 1993 @@ -208,7 +208,7 @@ int process_validdbregs(struct lwp *); int process_domem(struct lwp *, struct lwp *, struct uio *); -void process_stoptrace(void); +void process_stoptrace(int); void proc_reparent(struct proc *, struct proc *); void proc_changeparent(struct proc *, struct proc *);