The branch main has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=b2a270da9fbf0fb58fb7c1bf1006ae675e14a5e3
commit b2a270da9fbf0fb58fb7c1bf1006ae675e14a5e3 Author: Kyle Evans <[email protected]> AuthorDate: 2026-09-09 21:24:18 +0000 Commit: Kyle Evans <[email protected]> CommitDate: 2026-09-09 21:24:18 +0000 libjail: fix fetching mac.label for multiple jails When doing a basic `jls -n`, jls(8) will jailparam_get() the mac.label for every jail on the system using the same set of jailparams, and thus the same jp_value. We only init the mac_t the first time, so the first jail would populate it with `?` from /etc/mac.conf and the resulting jail_get(2) would clobber it with the empty string, then a second jail would try to pass the empty string to the kernel and fail because it must have a non-zero length. Fix it by invoking jps_get() every time. Drop some comments to note that jps_get() will be invoked with zero || garbage from previous call, and be sure that we don't leak our previous mac_t. There aren't any other jps_get implementations at this time, so this shouldn't cause any unexpected problems. Reported by: ivy Reviewed by: jamie Differential Revision: https://reviews.freebsd.org/D57280 --- lib/libjail/jail.c | 31 +++++++++++++++++++++++++------ usr.sbin/jail/tests/jail_basic_test.sh | 5 ++++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/lib/libjail/jail.c b/lib/libjail/jail.c index 95ba336b62ce..c180b8533e97 100644 --- a/lib/libjail/jail.c +++ b/lib/libjail/jail.c @@ -746,13 +746,23 @@ jailparam_get(struct jailparam *jp, unsigned njp, int flags) jiov[i].iov_base = jp[j].jp_name; jiov[i].iov_len = strlen(jp[j].jp_name) + 1; i++; - if (jp[j].jp_value == NULL && - !(jp[j].jp_flags & JP_RAWVALUE)) { - jp[j].jp_value = malloc(jp[j].jp_valuelen); + + /* + * We give structured types' jps_get() implementations + * a chance to initialize the value. We'll guarantee + * that the initial value is zeroed out, but they should + * assume on every call that the value may be populated + * by a subsequent jailparam_get(). + */ + if (!(jp[j].jp_flags & JP_RAWVALUE)) { if (jp[j].jp_value == NULL) { - strerror_r(errno, jail_errmsg, - JAIL_ERRMSGLEN); - return (-1); + jp[j].jp_value = calloc(1, + jp[j].jp_valuelen); + if (jp[j].jp_value == NULL) { + strerror_r(errno, jail_errmsg, + JAIL_ERRMSGLEN); + return (-1); + } } /* @@ -1435,6 +1445,15 @@ jps_get_mac_label(struct jailparam *jp, struct iovec *jiov) mac_t *pmac = jp->jp_value; int error; + /* + * Our value is only allocated once and may be reused for many + * jailparam_get() calls; avoid leaking. + */ + if (*pmac != NULL) { + mac_free(*pmac); + *pmac = NULL; + } + error = mac_prepare_type(pmac, "jail"); if (error != 0 && errno == ENOENT) { /* diff --git a/usr.sbin/jail/tests/jail_basic_test.sh b/usr.sbin/jail/tests/jail_basic_test.sh index cb50a94a45e8..c662e44f1a16 100755 --- a/usr.sbin/jail/tests/jail_basic_test.sh +++ b/usr.sbin/jail/tests/jail_basic_test.sh @@ -35,6 +35,9 @@ basic_body() { # Create the jail atf_check -s exit:0 -o ignore jail -c name=basejail persist ip4.addr=192.0.1.1 + # Create a second jail to test `jls -n` in the process for breakage when + # handling some of the non-trivial parameter types. + atf_check -s exit:0 -o ignore jail -c name=basejail2 persist ip4.addr=192.0.1.2 # Check output of jls atf_check -s exit:0 -o ignore jls atf_check -s exit:0 -o ignore jls -v @@ -52,7 +55,7 @@ basic_body() basic_cleanup() { - jail -r basejail + jail -r basejail basejail2 } atf_test_case "list" "cleanup"
