git: 38dd686b9336 - main - jaildesc: Publish the new fd only after the jaildesc is initialized

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 06 Jul 2026 12:55:21 UTC
The branch main has been updated by markj:

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

commit 38dd686b9336e2de5deadc5f8cb5e46a845b0dd9
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-07-06 12:51:11 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-07-06 12:51:11 +0000

    jaildesc: Publish the new fd only after the jaildesc is initialized
    
    jaildesc_alloc() finishes initializing the file structure only after it
    is made visible from the file descriptor table via finit().  In that
    window, other threads could try to perform operations on the descriptor
    and thus access an incompletely initialized jaildesc.
    
    Defer the finit() call until locks are initialized.  While here,
    simplify the error path for falloc_caps().
    
    Reported by:    Yuxiang Yang, Yizhou Zhao, Ao Wang, Xuewei Feng, Qi Li,
                    and Ke Xu from Tsinghua University using GLM-5.2 from Z.ai
    Reviewed by:    jamie
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D58049
---
 sys/kern/kern_jaildesc.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/sys/kern/kern_jaildesc.c b/sys/kern/kern_jaildesc.c
index e2e3246ea92b..fdce321cb468 100644
--- a/sys/kern/kern_jaildesc.c
+++ b/sys/kern/kern_jaildesc.c
@@ -153,18 +153,16 @@ jaildesc_alloc(struct thread *td, struct file **fpp, int *fdp, int owning)
 		if (error != 0)
 			return (error);
 	}
-	jd = malloc(sizeof(*jd), M_JAILDESC, M_WAITOK | M_ZERO);
 	error = falloc_caps(td, &fp, fdp, 0, NULL);
-	if (error != 0) {
-		free(jd, M_JAILDESC);
+	if (error != 0)
 		return (error);
-	}
-	finit(fp, priv_check_cred(fp->f_cred, PRIV_JAIL_SET) == 0 ?
-	    FREAD | FWRITE : FREAD, DTYPE_JAILDESC, jd, &jaildesc_ops);
+	jd = malloc(sizeof(*jd), M_JAILDESC, M_WAITOK | M_ZERO);
 	JAILDESC_LOCK_INIT(jd);
 	knlist_init_mtx(&jd->jd_selinfo.si_note, &jd->jd_lock);
 	if (owning)
 		jd->jd_flags |= JDF_OWNING;
+	finit(fp, priv_check_cred(fp->f_cred, PRIV_JAIL_SET) == 0 ?
+	    FREAD | FWRITE : FREAD, DTYPE_JAILDESC, jd, &jaildesc_ops);
 	*fpp = fp;
 	return (0);
 }