git: 79af745f4c29 - main - jail: Fix a race in prison_deref()

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Fri, 25 Sep 2026 17:00:45 UTC
The branch main has been updated by markj:

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

commit 79af745f4c29ab3df037fcf0a4b4fb1ea393825f
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-09-25 15:16:24 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-09-25 16:50:41 +0000

    jail: Fix a race in prison_deref()
    
    If we're killing a jail which has some user refs pending, then we would
    first drop our ref and then kill all processes in the prison.  However,
    it's possible for the prison to be freed before we finish that
    operation, generally if the processes exit on their own before
    prison_proc_iterate() returns.
    
    Thus, defer the release of the prison refcount until after we've killed
    all procs.
    
    Reviewed by:    jamie
    MFC after:      2 weeks
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D59984
---
 sys/kern/kern_jail.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 31b7c4a1e4f6..79922c3a0d38 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -3723,8 +3723,10 @@ prison_deref(struct prison *pr, int flags)
 			 * that need to be killed, either in this prison or its
 			 * descendants.
 			 */
-			if (refcount_load(&pr->pr_uref) > 0)
+			if (refcount_load(&pr->pr_uref) > 0) {
 				killpr = pr;
+				flags &= ~PD_DEREF;
+			}
 			/* Make sure the parent prison doesn't get killed. */
 			flags &= ~PD_KILL;
 		}
@@ -3794,8 +3796,10 @@ prison_deref(struct prison *pr, int flags)
 		sx_xunlock(&allprison_lock);
 
 	/* Kill any processes attached to a killed prison. */
-	if (killpr != NULL)
+	if (killpr != NULL) {
 		prison_proc_iterate(killpr, prison_kill_processes_cb, NULL);
+		prison_free(killpr);
+	}
 
 	/*
 	 * Finish removing any unreferenced prisons, which couldn't happen