From nobody Mon Dec 16 14:46:10 2024 X-Original-To: dev-commits-src-main@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 4YBjS24Qzxz5hWfl; Mon, 16 Dec 2024 14:46:10 +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 "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4YBjS221L3z4fBv; Mon, 16 Dec 2024 14:46:10 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1734360370; 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=cuGsfF+q+FFmJLnTF1BD7wXNzDNF3SXX/wHE/+DSJAs=; b=ovzn5CwBlJwKztVn/kEES402USZREisshPMWSDkVGW0H+v59xnNAPEzWBQ2zCYKE+LodHO lxACEMbQfuLFSuGlmnS7tkEwunXxqGog4vmCh65rDfsegC/82ZGrI4iq+kTYuu5RDmhJ0R bfPWis9m6wNsLjjyb/7/lR2ShOHYQ7YPEOTPwO5DyT5CwMXkvZV8Go+3tXmftqkNakt9BT fUCDpj0wUMfoLmPqV6zzrDHSBJY9jl4wbfUzbbjATR02ByYyckUa1FXpW2t2VWtRTh5i11 LUWjRjScI88ejLiFW1KZQiUF1x0S5gVtWjWelPDyNLkbO57Hnv1uGP8R/0Q7Dw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1734360370; 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=cuGsfF+q+FFmJLnTF1BD7wXNzDNF3SXX/wHE/+DSJAs=; b=jEknN1P9L0gXjC5idtDaTULYvaJqqpnC8qxVpKN34nglt7i1u+jIUMr2CmKp8LCbpiAIPz CGO5P8HNAhuxUCRaLdN3/h3rOpeaGHBm4o//MSod5PrqsxwRJ5+6Uj9DvNc2klDJeCYbkX A0lORqd4Q20gXmCK1Uul44OMyJvV2lAUDzwftGkdD8fnvdUNC9ieLrDiMIOP4KHyYHWiNn W0OammbRqhuYaX84iGaaBNvKLrcKVnv612g+5rf2VJAyIS8/QpP4ZE6sUX4EabiiZ+2iz3 MFKjPvb6cTcYr58wJL1vXGUs0H/8MAJSMIfjIiSJPj7s3PeUGPMjQIw6lHqDvw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1734360370; a=rsa-sha256; cv=none; b=ERJ1+4ulqWOPZRO3d9UXdcWkPqpALSfNWW4w9/TP2UpfVTlgL3bYqzqxMcfFbfAa3qqxZs AvQKUJToVi5BE+eNKKHDoBpb35OJ8KPp4q3Cbf6eSaYIzyJ/SDYTk20e3EVILfG5A52zVo Y0HPjvBlYN5ySHfwERjlSiYrjmWYeCCckCgppVYRiuCSoBcoBoHpvD8+lc1XHJXcPg9ACX vp6UGKmNwfVgWRhTXhozbmNIz1Ee4Q32PQm1aNYnkC0w443VkGLIl1sf3apRIUOErUFU++ u6PbLyffUGV7ieLVmGocNpHkuoAdBEkrC40rjGCd2vVmTg+6RNq/8/EuDEmqjQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4YBjS21dj5zxnP; Mon, 16 Dec 2024 14:46:10 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 4BGEkAab054009; Mon, 16 Dec 2024 14:46:10 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 4BGEkALn054006; Mon, 16 Dec 2024 14:46:10 GMT (envelope-from git) Date: Mon, 16 Dec 2024 14:46:10 GMT Message-Id: <202412161446.4BGEkALn054006@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Olivier Certner Subject: git: 3d8d91a5b32c - main - MAC/do: Introduce rules reference counting List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org 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/main X-Git-Reftype: branch X-Git-Commit: 3d8d91a5b32c219c7ee47840dcacbaf8c7480267 Auto-Submitted: auto-generated The branch main has been updated by olce: URL: https://cgit.FreeBSD.org/src/commit/?id=3d8d91a5b32c219c7ee47840dcacbaf8c7480267 commit 3d8d91a5b32c219c7ee47840dcacbaf8c7480267 Author: Olivier Certner AuthorDate: 2024-07-19 15:30:00 +0000 Commit: Olivier Certner CommitDate: 2024-12-16 14:42:39 +0000 MAC/do: Introduce rules reference counting This is going to be used in subsequent commits to keep rules alive even if disconnected from their jail in the meantime. We'll indeed have to release the prison lock between two uses (outright rejection, final granting) where the rules must absolutely stay the same for security reasons. Reviewed by: bapt Approved by: markj (mentor) Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D47619 --- sys/security/mac_do/mac_do.c | 63 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/sys/security/mac_do/mac_do.c b/sys/security/mac_do/mac_do.c index decfb3c756f0..7527732eae1a 100644 --- a/sys/security/mac_do/mac_do.c +++ b/sys/security/mac_do/mac_do.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -159,8 +160,9 @@ struct rule { TAILQ_HEAD(rulehead, rule); struct rules { - char string[MAC_RULE_STRING_LEN]; - struct rulehead head; + char string[MAC_RULE_STRING_LEN]; + struct rulehead head; + volatile u_int use_count __aligned(CACHE_LINE_SIZE); }; /* @@ -327,6 +329,7 @@ alloc_rules(void) _Static_assert(MAC_RULE_STRING_LEN > 0, "MAC_RULE_STRING_LEN <= 0!"); rules->string[0] = 0; TAILQ_INIT(&rules->head); + rules->use_count = 0; return (rules); } @@ -1027,16 +1030,46 @@ find_rules(struct prison *const pr, struct prison **const aprp) return (rules); } +static void +hold_rules(struct rules *const rules) +{ + refcount_acquire(&rules->use_count); +} + +static void +drop_rules(struct rules *const rules) +{ + if (refcount_release(&rules->use_count)) + toast_rules(rules); +} + +#ifdef INVARIANTS +static void +check_rules_use_count(const struct rules *const rules, u_int expected) +{ + const u_int use_count = refcount_load(&rules->use_count); + + if (use_count != expected) + panic("MAC/do: Rules at %p: Use count is %u, expected %u", + rules, use_count, expected); +} +#else +#define check_rules_use_count(...) +#endif /* INVARIANTS */ + /* * OSD destructor for slot 'osd_jail_slot'. * - * Called with 'value' not NULL. + * Called with 'value' not NULL. We have arranged that it is only ever called + * when the corresponding jail goes down or at module unload. */ static void dealloc_osd(void *const value) { struct rules *const rules = value; + /* No one should be using the rules but us at this point. */ + check_rules_use_count(rules, 1); toast_rules(rules); } @@ -1051,10 +1084,28 @@ dealloc_osd(void *const value) static void remove_rules(struct prison *const pr) { + struct rules *old_rules; + int error __unused; + prison_lock(pr); - /* This calls destructor dealloc_osd(). */ + /* + * We go to the burden of extracting rules first instead of just letting + * osd_jail_del() calling dealloc_osd() as we want to decrement their + * use count, and possibly free them, outside of the prison lock. + */ + old_rules = osd_jail_get(pr, osd_jail_slot); + error = osd_jail_set(pr, osd_jail_slot, NULL); + /* osd_set() never fails nor allocate memory when 'value' is NULL. */ + MPASS(error == 0); + /* + * This completely frees the OSD slot, but doesn't call the destructor + * since we've just put NULL in the slot. + */ osd_jail_del(pr, osd_jail_slot); prison_unlock(pr); + + if (old_rules != NULL) + drop_rules(old_rules); } /* @@ -1066,6 +1117,8 @@ set_rules(struct prison *const pr, struct rules *const rules) struct rules *old_rules; void **rsv; + check_rules_use_count(rules, 0); + hold_rules(rules); rsv = osd_reserve(osd_jail_slot); prison_lock(pr); @@ -1073,7 +1126,7 @@ set_rules(struct prison *const pr, struct rules *const rules) osd_jail_set_reserved(pr, osd_jail_slot, rsv, rules); prison_unlock(pr); if (old_rules != NULL) - toast_rules(old_rules); + drop_rules(old_rules); } /*