From nobody Mon Jun 29 19:25:44 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gpx891BrSz6jjZ5 for ; Mon, 29 Jun 2026 19:25:45 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gpx884LhCz40MT for ; Mon, 29 Jun 2026 19:25:44 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782761144; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=eIoEKVF8gf7unTy7jXhDy+axGl8Kztk2lvPdAmeGRLU=; b=mz7rUUwuZyjltbOZhbY3+On9zGCgzpy1Mou6L1oIYBaKA6ZzXRB0iD4+0eMFmyGGB1EJT9 pw/aeVQraPkLBuOvaKECKRkhB5G4yYZmW5vvEKrqRj2ecolB4bu6KO0rLkoOb+aLSTKWE2 hg9SMpzOTnJVzQDyLZFLO2Aapcu2JJe8n/DBFABunfwusZjQ1HCkRToc0Ti4kV/uUCDkL4 Q9mPBiDszW99IMQkJ2vM2OOgrTBXkHC0l7s1X06zGgiXVntNa15wECeSUoGSGqFqzKaTgl Sx4+iQXORkWN2qOCRjZDF2CQxipBwMLvuMaAmDGbzT0xmfp9PaUZsNA63exqfw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1782761144; a=rsa-sha256; cv=none; b=J7ZSuem8U4Qs0LI+3zzj2l6L6lck6kGcD1VSL8MCwdPIIz2pfhWLJGrRbPANVyIOdoQOxI Mo4zxO6jXBVhSiZpIFnlpbUs/3OVA70gZIjk+r5e+UT+udwnRo31R/Kl6ZD1o8QvJPrONn LNaWArcMRkoUiv6AOBI+kbYZ7+4LMNU/qe7sSmjtYyie/kRZ/Vpx6QsGMksiqZTPQwUpue eFWoVSIR72JH8h4z5dgGImyZZdq6V7Jck0B/pmqtDbwaYRCX9K8//vkgIn9lK0r4jaxL/x YGGxf11NrQdr6SDmEv28IEIA4mNSC9I2g8Ae0hy3fqtj6FjeQzpsDLH0+8ZRcQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1782761144; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=eIoEKVF8gf7unTy7jXhDy+axGl8Kztk2lvPdAmeGRLU=; b=IkbMwKLyOf1h+JN8mZB8IKqpB59qPtvwwapWbAka3Rsn+hwwPGLrd/GahpPdILDwgRNV0Z l6H/t06zy9MZhRReq6t1zWg/s+a3de0ALxgYGaJa2HSRwThWTkmQ9Pfk0qyL71q9pAf23R 09Aa1whk6m+G9IEGNtxzJAl1g3gia7/SwBuf4c9k0r/oVoitOHyYhyG0tJjtpoeIAXM8eY Md0T3v5Vk+i4NUOabF+pYAUexIrZgdiWjNIG9fGZVw/6DV54M0L95yV3ZK4rmKA/jyM9Rb KjmUqBAeqVOl83QSzb5Slr0U/p8lamBJzC+Kt666wo6nBedjDdOCtSrFMRmlWw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gpx883QMyz19cY for ; Mon, 29 Jun 2026 19:25:44 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1feee by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 29 Jun 2026 19:25:44 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Olivier Certner Subject: git: 56e1a621d0b4 - stable/15 - MAC/do: find_conf(): Return configuration with a true reference List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: olce X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: 56e1a621d0b4d0cbf054822fcfcafffd92c8d3a4 Auto-Submitted: auto-generated Date: Mon, 29 Jun 2026 19:25:44 +0000 Message-Id: <6a42c6b8.1feee.47ba239f@gitrepo.freebsd.org> The branch stable/15 has been updated by olce: URL: https://cgit.FreeBSD.org/src/commit/?id=56e1a621d0b4d0cbf054822fcfcafffd92c8d3a4 commit 56e1a621d0b4d0cbf054822fcfcafffd92c8d3a4 Author: Olivier Certner AuthorDate: 2026-04-27 14:39:15 +0000 Commit: Olivier Certner CommitDate: 2026-06-29 19:23:43 +0000 MAC/do: find_conf(): Return configuration with a true reference In addition to the applicable configuration, find_conf() was returning a pointer to the actual jail holding the configuration object, with that jail's mutex locked in order to ensure liveness of the returned configuration (if we wouldn't, a concurrent thread modifying the jail's configuration could destroy this configuration object underneath us). But: 1. Ensuring configuration stability by owning the holding jail's mutex requires callers to either keep that mutex locked for a longer period of time than just accessing the corresponding 'struct prison' (in general, bad for concurrency with other operations involving jails) or to perform an additional dance to acquire a real reference in case the jail's mutex, for some reason (in general, LORs or acquiring a sleepable lock) must be dropped before use. 2. Most code does not actually need to know which jail holds the applicable configuration but for unlocking the jail's mutex. Having to deal with the jail holding the configuration can cause confusion about which jail (the current one, or the one holding the configuration) must be used (and actually did in the very initial version of MAC/do, which had a serious flaw as a consequence). So, do not keep a lock on the holding jail. Instead, ensure configuration stability by always acquiring a true reference from the start and passing it to the caller. Those callers not doing the dance mentioned above now need to free it when finished (but this need replaces the one to unlock the prison). Additionally, only return the holding jail if explicitly requested by the caller. mac_do_jail_get() is currently the only caller that needs it, in order to be able to reliably report if the configuration is inherited. Reviewed by: bapt MFC after: 1 month Sponsored by: The FreeBSD Foundation Pull Request: https://ron-dev.freebsd.org/FreeBSD/src/pulls/38 (cherry picked from commit 4e4cf18b85cc51f41bcae20114f9c0e7b69f76e0) --- sys/security/mac_do/mac_do.c | 83 +++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/sys/security/mac_do/mac_do.c b/sys/security/mac_do/mac_do.c index e844cda7e1c4..19ea3768153d 100644 --- a/sys/security/mac_do/mac_do.c +++ b/sys/security/mac_do/mac_do.c @@ -1180,14 +1180,19 @@ drop_conf(struct conf *const conf) /* * Find configuration applicable to the passed prison. * - * Returns the applicable configuration (and never NULL). 'pr' must be - * unlocked. 'aprp' is set to the (ancestor) prison holding these, and it must - * be unlocked once the caller is done accessing the configuration. '*aprp' is - * equal to 'pr' if and only if the current jail has its own specific - * configuration. + * Returns the applicable configuration (which always exists), with an + * additional reference that must be freed by the caller. 'pr' must not be + * locked. + * + * The applicable configuration is that of the closest ancestor prison + * (including itself) of the passed prison that actually has a 'struct conf' + * associated to it. + * + * If 'hpr' is not NULL, it is used to return a pointer to the (unlocked) prison + * holding the applicable configuration. */ static struct conf * -find_conf(struct prison *const pr, struct prison **const aprp) +find_conf(struct prison *const pr, struct prison **const hpr) { struct prison *cpr, *ppr; struct conf *conf; @@ -1213,7 +1218,11 @@ find_conf(struct prison *const pr, struct prison **const aprp) cpr = ppr; } - *aprp = cpr; + hold_conf(conf); + prison_unlock(cpr); + + if (hpr != NULL) + *hpr = cpr; return (conf); } @@ -1388,7 +1397,6 @@ static int parse_and_set_conf(struct prison *pr, const char *rules_string, const char *exec_paths_string, struct parse_error **parse_error) { - struct prison *ppr = NULL; struct conf *applicable_conf = NULL; struct conf *conf; int error = 0; @@ -1397,11 +1405,8 @@ parse_and_set_conf(struct prison *pr, const char *rules_string, need_applicable_conf = (rules_string == NULL || rules_string[0] == '\0' || exec_paths_string == NULL || exec_paths_string[0] == '\0'); - if (need_applicable_conf) { - applicable_conf = find_conf(pr, &ppr); - hold_conf(applicable_conf); - prison_unlock(ppr); - } + if (need_applicable_conf) + applicable_conf = find_conf(pr, NULL); conf = alloc_conf(); @@ -1439,22 +1444,20 @@ static int mac_do_sysctl_rules(SYSCTL_HANDLER_ARGS) { char *const buf = malloc(MAX_RULE_STRING_SIZE, M_MAC_DO, M_WAITOK); - struct prison *const td_pr = req->td->td_ucred->cr_prison; - struct prison *pr; + struct prison *const pr = req->td->td_ucred->cr_prison; struct conf *conf; struct parse_error *parse_error = NULL; int error; - conf = find_conf(td_pr, &pr); + conf = find_conf(pr, NULL); strlcpy(buf, conf->rules.string, MAX_RULE_STRING_SIZE); - prison_unlock(pr); error = sysctl_handle_string(oidp, buf, MAX_RULE_STRING_SIZE, req); if (error != 0 || req->newptr == NULL) goto out; /* Set our prison's rules, not that of the jail we inherited from. */ - error = parse_and_set_conf(td_pr, buf, NULL, &parse_error); + error = parse_and_set_conf(pr, buf, NULL, &parse_error); if (error != 0) { if (print_parse_error) printf("MAC/do: Parse error at index %zu: %s\n", @@ -1463,6 +1466,7 @@ mac_do_sysctl_rules(SYSCTL_HANDLER_ARGS) } out: + drop_conf(conf); free(buf, M_MAC_DO); return (error); } @@ -1481,21 +1485,19 @@ static int mac_do_sysctl_exec_paths(SYSCTL_HANDLER_ARGS) { char *const buf = malloc(MAX_EXEC_PATHS_SIZE, M_MAC_DO, M_WAITOK); - struct prison *const td_pr = req->td->td_ucred->cr_prison; - struct prison *pr; + struct prison *const pr = req->td->td_ucred->cr_prison; struct conf *conf; struct parse_error *parse_error = NULL; int error; - conf = find_conf(td_pr, &pr); + conf = find_conf(pr, NULL); strlcpy(buf, conf->exec_paths.exec_paths_str, MAX_EXEC_PATHS_SIZE); - prison_unlock(pr); error = sysctl_handle_string(oidp, buf, MAX_EXEC_PATHS_SIZE, req); if (error != 0 || req->newptr == NULL) goto out; - error = parse_and_set_conf(td_pr, NULL, buf, &parse_error); + error = parse_and_set_conf(pr, NULL, buf, &parse_error); if (error != 0) { if (print_parse_error) printf("MAC/do: Parse error at index %zu: %s\n", @@ -1504,6 +1506,7 @@ mac_do_sysctl_exec_paths(SYSCTL_HANDLER_ARGS) } out: + drop_conf(conf); free(buf, M_MAC_DO); return (error); } @@ -1529,20 +1532,19 @@ mac_do_jail_create(void *obj, void *data) static int mac_do_jail_get(void *obj, void *data) { - struct prison *ppr, *const pr = obj; + struct prison *const pr = obj; struct vfsoptlist *const opts = data; - struct conf *conf; - struct rules *rules; - struct exec_paths *exec_paths; + struct prison *hpr_out; + struct conf *const applicable_conf = find_conf(pr, &hpr_out); + const struct prison *const hpr = hpr_out; + const struct rules *const rules = &applicable_conf->rules; + const struct exec_paths *const exec_paths = &applicable_conf->exec_paths; int jsys, error; - conf = find_conf(pr, &ppr); - rules = &conf->rules; - exec_paths = &conf->exec_paths; - - jsys = pr == ppr ? + jsys = hpr == pr ? (STAILQ_EMPTY(&rules->head) ? JAIL_SYS_DISABLE : JAIL_SYS_NEW) : JAIL_SYS_INHERIT; + error = vfs_setopt(opts, "mac.do", &jsys, sizeof(jsys)); if (error != 0 && error != ENOENT) goto done; @@ -1558,7 +1560,7 @@ mac_do_jail_get(void *obj, void *data) error = 0; done: - prison_unlock(ppr); + drop_conf(applicable_conf); return (error); } @@ -2292,11 +2294,10 @@ mac_do_priv_grant(struct ucred *cred, int priv) static int check_proc(void) { + struct prison *const pr = curproc->p_ucred->cr_prison; char *path, *to_free; struct conf *conf; struct exec_paths *exec_paths; - struct prison *td_pr; - struct prison *pr; int error; /* @@ -2321,8 +2322,7 @@ check_proc(void) return (EPERM); error = EPERM; - td_pr = curproc->p_ucred->cr_prison; - conf = find_conf(td_pr, &pr); + conf = find_conf(pr, NULL); exec_paths = &conf->exec_paths; for (int i = 0; i < exec_paths->exec_path_count; i++) @@ -2331,8 +2331,7 @@ check_proc(void) break; } - prison_unlock(pr); - + drop_conf(conf); free(to_free, M_TEMP); return (error); } @@ -2340,7 +2339,7 @@ check_proc(void) static void mac_do_setcred_enter(void) { - struct prison *pr; + struct prison *const pr = curproc->p_ucred->cr_prison; struct mac_do_setcred_data * data; struct conf *conf; int error; @@ -2364,9 +2363,7 @@ mac_do_setcred_enter(void) /* * Find the currently applicable rules. */ - conf = find_conf(curproc->p_ucred->cr_prison, &pr); - hold_conf(conf); - prison_unlock(pr); + conf = find_conf(pr, NULL); /* * Setup thread data to be used by other hooks.