From nobody Thu Apr 03 19:32:26 2025 X-Original-To: dev-commits-src-branches@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 4ZTBhV4sgvz5sMCP; Thu, 03 Apr 2025 19:32:26 +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 4ZTBhV2jsVz3Sr8; Thu, 03 Apr 2025 19:32:26 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1743708746; 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=k/u9cEayx55aY1AmUjXxKEtodZi0WZO9RdVToOg0DhE=; b=Ce+5e8w2V0dhaDQv+CZu9x4M0vbnaOHqx3GkiKSPVT4CQ4jmbSQ6ziKn9oKBkIu3aeNEjX 7Dja/5a/Uj3OiG1DFnkUH7+wdGbkmfOBPqfCkevCmnudlzwqJtU95OrcTMVsEBS5FHlRmf KF6sFJyP960u156cYRMP96EvowHKxou0EZCoS5u2RpYatyQ+OdDxr9u+XGAziuiCZPp9Kt /D6YYgKd8nagbDDtMtoo3s9LS5C1aBIgqZV5gFgEIBxuh1uSS87+oVD71fCvzbx6tgGsBx S1kAaGXStVdta+ILuEoMtLA4IAveO2R27rhszJ7ZNDpYDhFaaUo1pn4TEEWdQQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1743708746; a=rsa-sha256; cv=none; b=iGZFSPWQ27E4YYrbfIJbYQyWKl351vnvFfz2L1wxzWQ+zp81F2v9e2r3UJ6c9xKzpN55ao 6FdiBdmS1JbfBf0SX5FOEYl0C+P4xClNua9+Wl/22R04GeTgcTwHDtu6Rtkqs7m1TF/crQ uZlGSZ9MAjEmPvLC2d/TDUjWpifNk6pCs6eGmL71nfK5/butWeG6IZe1KuSuaZ9/g/B/GC BO2c1F48+5k5zhQ8LnDiWdA05nMomcY9x6chSPfE7kwYZVClXOLxe/f3v4BnNI6CWzWOrR LpAXSdIi6egvdAAoJZY73a6V91yeHkuK5h0mRybWhlqZQsvokiKsHhnbqLboHA== 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=1743708746; 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=k/u9cEayx55aY1AmUjXxKEtodZi0WZO9RdVToOg0DhE=; b=IetgRhXijEZKo25TWtwZUCG8q9nuSeyffBe57guu/jG91qX3PLyBgFrH0OB707XG5ylfsl by3wMGb01fViC2r7ZgwvM3ab1Wgjq/SFc4UZsuqMhlvc4wf1d+vxC66JnHrLdiIoKZl5VR GLUk4o4cZSJfm+eU51CXLUEmhLa3rrG5UzFsRoE1Sd+Ms0VSbU+I8yFgia8AGLMOyM+x0t 5Ubuk2PzZYkZjqU8tz2ntlz0AmTR5agahEvfbBjC/HJYF6puYB4L5SUgrMSVjSAF1SOdxk /uI3e3ZVdTTAWY8E2M8s3uwh5jdi/2NM+ggFTlICkbea4AKkdvrV79e+WUN90g== 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 4ZTBhV2HVHzM2; Thu, 03 Apr 2025 19:32:26 +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 533JWQa8040468; Thu, 3 Apr 2025 19:32:26 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 533JWQv6040465; Thu, 3 Apr 2025 19:32:26 GMT (envelope-from git) Date: Thu, 3 Apr 2025 19:32:26 GMT Message-Id: <202504031932.533JWQv6040465@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Olivier Certner Subject: git: 1780d3f3d1a7 - stable/14 - MAC/do: Introduce rules reference counting List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@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/stable/14 X-Git-Reftype: branch X-Git-Commit: 1780d3f3d1a777934e39442a346a9bc28d6acc26 Auto-Submitted: auto-generated The branch stable/14 has been updated by olce: URL: https://cgit.FreeBSD.org/src/commit/?id=1780d3f3d1a777934e39442a346a9bc28d6acc26 commit 1780d3f3d1a777934e39442a346a9bc28d6acc26 Author: Olivier Certner AuthorDate: 2024-07-19 15:30:00 +0000 Commit: Olivier Certner CommitDate: 2025-04-03 19:31:04 +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 (cherry picked from commit 3d8d91a5b32c219c7ee47840dcacbaf8c7480267) --- 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); } /*