Module Name:    src
Committed By:   kamil
Date:           Thu Oct  3 22:48:44 UTC 2019

Modified Files:
        src/sys/kern: kern_exit.c kern_lwp.c kern_sig.c kern_synch.c
            sys_ptrace_common.c

Log Message:
Separate flag for suspended by _lwp_suspend and suspended by a debugger

Once a thread was stopped with ptrace(2), userland process must not
be able to unstop it deliberately or by an accident.

This was a Windows-style behavior that makes threading tracing fragile.


To generate a diff of this commit:
cvs rdiff -u -r1.276 -r1.277 src/sys/kern/kern_exit.c
cvs rdiff -u -r1.203 -r1.204 src/sys/kern/kern_lwp.c
cvs rdiff -u -r1.365 -r1.366 src/sys/kern/kern_sig.c
cvs rdiff -u -r1.323 -r1.324 src/sys/kern/kern_synch.c
cvs rdiff -u -r1.61 -r1.62 src/sys/kern/sys_ptrace_common.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_exit.c
diff -u src/sys/kern/kern_exit.c:1.276 src/sys/kern/kern_exit.c:1.277
--- src/sys/kern/kern_exit.c:1.276	Thu Jun 13 20:20:18 2019
+++ src/sys/kern/kern_exit.c	Thu Oct  3 22:48:44 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_exit.c,v 1.276 2019/06/13 20:20:18 kamil Exp $	*/
+/*	$NetBSD: kern_exit.c,v 1.277 2019/10/03 22:48:44 kamil Exp $	*/
 
 /*-
  * Copyright (c) 1998, 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.276 2019/06/13 20:20:18 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.277 2019/10/03 22:48:44 kamil Exp $");
 
 #include "opt_ktrace.h"
 #include "opt_dtrace.h"
@@ -617,6 +617,7 @@ retry:
 		l2->l_flag |= LW_WEXIT;
 		if ((l2->l_stat == LSSLEEP && (l2->l_flag & LW_SINTR)) ||
 		    l2->l_stat == LSSUSPENDED || l2->l_stat == LSSTOP) {
+			l2->l_flag &= ~LW_DBGSUSPEND;
 		    	/* setrunnable() will release the lock. */
 			setrunnable(l2);
 			continue;

Index: src/sys/kern/kern_lwp.c
diff -u src/sys/kern/kern_lwp.c:1.203 src/sys/kern/kern_lwp.c:1.204
--- src/sys/kern/kern_lwp.c:1.203	Mon Sep 30 21:13:33 2019
+++ src/sys/kern/kern_lwp.c	Thu Oct  3 22:48:44 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_lwp.c,v 1.203 2019/09/30 21:13:33 kamil Exp $	*/
+/*	$NetBSD: kern_lwp.c,v 1.204 2019/10/03 22:48:44 kamil Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -211,7 +211,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.203 2019/09/30 21:13:33 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.204 2019/10/03 22:48:44 kamil Exp $");
 
 #include "opt_ddb.h"
 #include "opt_lockdebug.h"
@@ -408,6 +408,11 @@ lwp_suspend(struct lwp *curl, struct lwp
 		return (EDEADLK);
 	}
 
+	if ((t->l_flag & LW_DBGSUSPEND) != 0) {
+		lwp_unlock(t);
+		return 0;
+	}
+
 	error = 0;
 
 	switch (t->l_stat) {
@@ -472,7 +477,7 @@ lwp_continue(struct lwp *l)
 
 	l->l_flag &= ~LW_WSUSPEND;
 
-	if (l->l_stat != LSSUSPENDED) {
+	if (l->l_stat != LSSUSPENDED || (l->l_flag & LW_DBGSUSPEND) != 0) {
 		lwp_unlock(l);
 		return;
 	}
@@ -497,6 +502,8 @@ lwp_unstop(struct lwp *l)
 
 	lwp_lock(l);
 
+	KASSERT((l->l_flag & LW_DBGSUSPEND) == 0);
+
 	/* If not stopped, then just bail out. */
 	if (l->l_stat != LSSTOP) {
 		lwp_unlock(l);

Index: src/sys/kern/kern_sig.c
diff -u src/sys/kern/kern_sig.c:1.365 src/sys/kern/kern_sig.c:1.366
--- src/sys/kern/kern_sig.c:1.365	Mon Sep 30 21:13:33 2019
+++ src/sys/kern/kern_sig.c	Thu Oct  3 22:48:44 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_sig.c,v 1.365 2019/09/30 21:13:33 kamil Exp $	*/
+/*	$NetBSD: kern_sig.c,v 1.366 2019/10/03 22:48:44 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.365 2019/09/30 21:13:33 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.366 2019/10/03 22:48:44 kamil Exp $");
 
 #include "opt_ptrace.h"
 #include "opt_dtrace.h"
@@ -1108,11 +1108,20 @@ sigpost(struct lwp *l, sig_t action, int
 
 	SDT_PROBE(proc, kernel, , signal__send, l, p, sig, 0, 0);
 
+	lwp_lock(l);
+	if (__predict_false((l->l_flag & LW_DBGSUSPEND) != 0)) {
+		if ((prop & SA_KILL) != 0)
+			l->l_flag &= ~LW_DBGSUSPEND;
+		else {
+			lwp_unlock(l);
+			return 0;
+		}
+	}
+
 	/*
 	 * Have the LWP check for signals.  This ensures that even if no LWP
 	 * is found to take the signal immediately, it should be taken soon.
 	 */
-	lwp_lock(l);
 	l->l_flag |= LW_PENDSIG;
 
 	/*
@@ -2179,7 +2188,8 @@ sigexit(struct lwp *l, int signo)
 			LIST_FOREACH(t, &p->p_lwps, l_sibling) {
 				lwp_lock(t);
 				if (t == l) {
-					t->l_flag &= ~LW_WSUSPEND;
+					t->l_flag &=
+					    ~(LW_WSUSPEND | LW_DBGSUSPEND);
 					lwp_unlock(t);
 					continue;
 				}
@@ -2376,7 +2386,7 @@ proc_unstop(struct proc *p)
 
 	LIST_FOREACH(l, &p->p_lwps, l_sibling) {
 		lwp_lock(l);
-		if (l->l_stat != LSSTOP) {
+		if (l->l_stat != LSSTOP || (l->l_flag & LW_DBGSUSPEND) != 0) {
 			lwp_unlock(l);
 			continue;
 		}

Index: src/sys/kern/kern_synch.c
diff -u src/sys/kern/kern_synch.c:1.323 src/sys/kern/kern_synch.c:1.324
--- src/sys/kern/kern_synch.c:1.323	Sun Feb  3 03:19:28 2019
+++ src/sys/kern/kern_synch.c	Thu Oct  3 22:48:44 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_synch.c,v 1.323 2019/02/03 03:19:28 mrg Exp $	*/
+/*	$NetBSD: kern_synch.c,v 1.324 2019/10/03 22:48:44 kamil Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2004, 2006, 2007, 2008, 2009
@@ -69,7 +69,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.323 2019/02/03 03:19:28 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.324 2019/10/03 22:48:44 kamil Exp $");
 
 #include "opt_kstack.h"
 #include "opt_dtrace.h"
@@ -885,6 +885,7 @@ setrunnable(struct lwp *l)
 	struct cpu_info *ci;
 
 	KASSERT((l->l_flag & LW_IDLE) == 0);
+	KASSERT((l->l_flag & LW_DBGSUSPEND) == 0);
 	KASSERT(mutex_owned(p->p_lock));
 	KASSERT(lwp_locked(l, NULL));
 	KASSERT(l->l_mutex != l->l_cpu->ci_schedstate.spc_mutex);

Index: src/sys/kern/sys_ptrace_common.c
diff -u src/sys/kern/sys_ptrace_common.c:1.61 src/sys/kern/sys_ptrace_common.c:1.62
--- src/sys/kern/sys_ptrace_common.c:1.61	Tue Oct  1 21:49:50 2019
+++ src/sys/kern/sys_ptrace_common.c	Thu Oct  3 22:48:44 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_ptrace_common.c,v 1.61 2019/10/01 21:49:50 kamil Exp $	*/
+/*	$NetBSD: sys_ptrace_common.c,v 1.62 2019/10/03 22:48:44 kamil Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -118,7 +118,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.61 2019/10/01 21:49:50 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.62 2019/10/03 22:48:44 kamil Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ptrace.h"
@@ -787,9 +787,12 @@ ptrace_startstop(struct proc *t, struct 
 	DPRINTF(("%s: lwp=%d request=%d\n", __func__, (*lt)->l_lid, rq));
 	lwp_lock(*lt);
 	if (rq == PT_SUSPEND)
-		(*lt)->l_flag |= LW_WSUSPEND;
-	else
-		(*lt)->l_flag &= ~LW_WSUSPEND;
+		(*lt)->l_flag |= LW_DBGSUSPEND;
+	else {
+		(*lt)->l_flag &= ~LW_DBGSUSPEND;
+		if ((*lt)->l_flag != LSSUSPENDED)
+			(*lt)->l_stat = LSSTOP;
+	}
 	lwp_unlock(*lt);
 	return 0;
 }
@@ -1233,7 +1236,8 @@ do_ptrace(struct ptrace_methods *ptm, st
 		if (resume_all) {
 #ifdef PT_STEP
 			if (req == PT_STEP) {
-				if (lt->l_flag & LW_WSUSPEND) {
+				if (lt->l_flag &
+				    (LW_WSUSPEND | LW_DBGSUSPEND)) {
 					error = EDEADLK;
 					break;
 				}
@@ -1242,7 +1246,9 @@ do_ptrace(struct ptrace_methods *ptm, st
 			{
 				error = EDEADLK;
 				LIST_FOREACH(lt2, &t->p_lwps, l_sibling) {
-					if ((lt2->l_flag & LW_WSUSPEND) == 0) {
+					if ((lt2->l_flag &
+					    (LW_WSUSPEND | LW_DBGSUSPEND)) == 0
+					    ) {
 						error = 0;
 						break;
 					}
@@ -1251,7 +1257,7 @@ do_ptrace(struct ptrace_methods *ptm, st
 					break;
 			}
 		} else {
-			if (lt->l_flag & LW_WSUSPEND) {
+			if (lt->l_flag & (LW_WSUSPEND | LW_WSUSPEND)) {
 				error = EDEADLK;
 				break;
 			}

Reply via email to