git: b3b50cbd4647 - main - jail: return a new descriptor from jail_get(JAIL_USE_DESC | JAIL_GET_DESC)

From: Abdelkader Boudih <seuros_at_FreeBSD.org>
Date: Mon, 02 Nov 2026 20:10:24 UTC
The branch main has been updated by seuros:

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

commit b3b50cbd4647bb095e0cb5b72e933bc3036e412d
Author:     Abdelkader Boudih <seuros@FreeBSD.org>
AuthorDate: 2026-11-02 20:09:55 +0000
Commit:     Abdelkader Boudih <seuros@FreeBSD.org>
CommitDate: 2026-11-02 20:09:55 +0000

    jail: return a new descriptor from jail_get(JAIL_USE_DESC | JAIL_GET_DESC)
    
    Prior to this change, `jail_get` when called with `JAIL_USE|JAIL_GET_DESC`
    would fail to return a valid descriptor in the positive case because the
    `JAIL_USE_DESC` block jumped to `found_prison` before the descriptor was
    allocated. This resulted in the returned jail descriptor always being -1,
    despite the call being successful.
    
    This change fixes the logic so `jfd_out` is properly initialized in the
    aforementioned scenario.
    
    MFC after: 3 days
    
    Reviewed by:    jamie, ngie, adrian
    Differential Revision:  https://reviews.freebsd.org/D60984
---
 sys/kern/kern_jail.c      | 18 +++++++++++-------
 tests/sys/kern/jaildesc.c | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 3b9809671f21..ae22e43aef62 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -2645,6 +2645,17 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
 			vfs_opterror(opts, "unexpected desc");
 			goto done;
 		}
+		if (flags & (JAIL_GET_DESC | JAIL_OWN_DESC)) {
+			/*
+			 * Allocate a jail descriptor to return later.
+			 * This must happen before the JAIL_USE_DESC
+			 * lookup below, which jumps to found_prison.
+			 */
+			error = jaildesc_alloc(td, &jfp_out, &jfd_out,
+			    flags & JAIL_OWN_DESC);
+			if (error)
+				goto done;
+		}
 		if (flags & JAIL_USE_DESC) {
 			/* Get the jail from its descriptor. */
 			error = jaildesc_find(td, jfd_in, &pr, NULL);
@@ -2673,13 +2684,6 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
 			prison_free(mypr);
 			mypr = jdpr;
 		}
-		if (flags & (JAIL_GET_DESC | JAIL_OWN_DESC)) {
-			/* Allocate a jail descriptor to return later. */
-			error = jaildesc_alloc(td, &jfp_out, &jfd_out,
-				flags & JAIL_OWN_DESC);
-			if (error)
-				goto done;
-		}
 	} else
 		goto done;
 
diff --git a/tests/sys/kern/jaildesc.c b/tests/sys/kern/jaildesc.c
index 6c7993cfc1d3..99b759cfc9d1 100644
--- a/tests/sys/kern/jaildesc.c
+++ b/tests/sys/kern/jaildesc.c
@@ -389,6 +389,45 @@ ATF_TC_BODY(at_desc_bad_fd, tc)
 	ATF_REQUIRE_MSG(close(jd) == 0, "close: %s", strerror(errno));
 }
 
+/*
+ * Look a jail up by descriptor and ask for a descriptor back.
+ */
+ATF_TC(use_desc_get_desc);
+ATF_TC_HEAD(use_desc_get_desc, tc)
+{
+	atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(use_desc_get_desc, tc)
+{
+	struct iovec iov[2];
+	int desc, jd, jid, n;
+
+	jd = create_jail("jaildesc_use_desc_get_desc");
+
+	desc = jd;
+	n = 0;
+	iov[n].iov_base = __DECONST(void *, "desc");
+	iov[n++].iov_len = strlen("desc") + 1;
+	iov[n].iov_base = &desc;
+	iov[n++].iov_len = sizeof(desc);
+	jid = jail_get(iov, n, JAIL_USE_DESC | JAIL_GET_DESC);
+	ATF_REQUIRE_MSG(jid >= 0, "jail_get: %s", strerror(errno));
+	ATF_REQUIRE_MSG(desc >= 0 && desc != jd,
+	    "jail_get returned descriptor %d, input was %d", desc, jd);
+
+	/* The returned descriptor must name the same jail. */
+	n = 0;
+	iov[n].iov_base = __DECONST(void *, "desc");
+	iov[n++].iov_len = strlen("desc") + 1;
+	iov[n].iov_base = &desc;
+	iov[n++].iov_len = sizeof(desc);
+	ATF_REQUIRE_MSG(jail_get(iov, n, JAIL_USE_DESC) == jid,
+	    "jail_get: %s", strerror(errno));
+
+	ATF_REQUIRE_MSG(close(desc) == 0, "close: %s", strerror(errno));
+	ATF_REQUIRE_MSG(close(jd) == 0, "close: %s", strerror(errno));
+}
+
 ATF_TP_ADD_TCS(tp)
 {
 	ATF_TP_ADD_TC(tp, poll_close_race);
@@ -397,6 +436,7 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, curjail_get);
 	ATF_TP_ADD_TC(tp, self_destruct);
 	ATF_TP_ADD_TC(tp, at_desc_bad_fd);
+	ATF_TP_ADD_TC(tp, use_desc_get_desc);
 
 	return (atf_no_error());
 }