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 *);