git: d3000939c7b9 - main - P2_WEXIT: avoid thread_single() for exiting process earlier

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Mon, 13 Jun 2022 19:33:28 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=d3000939c7b94fc887f23dd8946861cf0fa1b73b

commit d3000939c7b94fc887f23dd8946861cf0fa1b73b
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2022-05-04 23:57:26 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2022-06-13 19:30:02 +0000

    P2_WEXIT: avoid thread_single() for exiting process earlier
    
    before the process itself does thread_single(SINGLE_EXIT).  We cannot
    single-thread such process in ALLPROC (external) mode, and properly
    detect and report the failure to do so due to the process becoming
    zombie is easier to prevent than handle.
    
    In collaboration with:  pho
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      2 weeks
    Differential revision:  https://reviews.freebsd.org/D35310
---
 sys/kern/kern_exit.c    | 2 ++
 sys/kern/kern_proc.c    | 2 +-
 sys/kern/kern_procctl.c | 2 +-
 sys/kern/kern_sig.c     | 1 +
 sys/sys/proc.h          | 3 +++
 5 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 0fc7a471f3f0..fcd9bffe862d 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -251,6 +251,8 @@ exit1(struct thread *td, int rval, int signo)
 	 * MUST abort all other threads before proceeding past here.
 	 */
 	PROC_LOCK(p);
+	p->p_flag2 |= P2_WEXIT;
+
 	/*
 	 * First check if some other thread or external request got
 	 * here before us.  If so, act appropriately: exit or suspend.
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index cd528d47830d..6796d672afd7 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -3446,7 +3446,7 @@ allproc_loop:
 			PROC_UNLOCK(p);
 			continue;
 		}
-		if ((p->p_flag & P_WEXIT) != 0) {
+		if ((p->p_flag2 & P2_WEXIT) != 0) {
 			seen_exiting = true;
 			PROC_UNLOCK(p);
 			continue;
diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c
index 9db9577fde3d..640ebc32ee55 100644
--- a/sys/kern/kern_procctl.c
+++ b/sys/kern/kern_procctl.c
@@ -325,7 +325,7 @@ reap_kill_proc(struct thread *td, struct proc *p2, ksiginfo_t *ksi,
 
 	res = true;
 	PROC_LOCK(p2);
-	if ((p2->p_flag & P_WEXIT) == 0) {
+	if ((p2->p_flag2 & P2_WEXIT) == 0) {
 		_PHOLD_LITE(p2);
 		res = reap_kill_proc_locked(td, p2, ksi, rk, error);
 		_PRELE(p2);
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index ce6f517262a4..afb2fd78c231 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -3406,6 +3406,7 @@ sigexit(struct thread *td, int sig)
 	struct proc *p = td->td_proc;
 
 	PROC_LOCK_ASSERT(p, MA_OWNED);
+	p->p_flag2 |= P2_WEXIT;
 	p->p_acflag |= AXSIG;
 	/*
 	 * We must be single-threading to generate a core dump.  This
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 223714724aca..5027cca5da8b 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -847,6 +847,9 @@ struct proc {
 #define	P2_NO_NEW_PRIVS		0x00008000	/* Ignore setuid */
 #define	P2_WXORX_DISABLE	0x00010000	/* WX mappings enabled */
 #define	P2_WXORX_ENABLE_EXEC	0x00020000	/* WXORX enabled after exec */
+#define	P2_WEXIT		0x00040000	/* exit just started, no
+						   external thread_single() is
+						   permitted */
 
 /* Flags protected by proctree_lock, kept in p_treeflags. */
 #define	P_TREE_ORPHANED		0x00000001	/* Reparented, on orphan list */