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
This commit is contained in:
Abdelkader Boudih committed 2026-11-02 21:09:55 +01:00
1 parent 6c177745c5
commit b3b50cbd46
2 files changed
+51 -7

No files matched your search

+11 -7
View File
@@ -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;
+40
View File
@@ -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());
}