git: b3b50cbd4647 - main - jail: return a new descriptor from jail_get(JAIL_USE_DESC | JAIL_GET_DESC)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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());
}