From nobody Thu Apr 23 18:48:09 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 4g1lTq07MCz6bKG1 for ; Thu, 23 Apr 2026 18:48:15 +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 "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4g1lTp3TLmz3d4G for ; Thu, 23 Apr 2026 18:48:14 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1776970094; 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=pWV0h92KbmoMjo47blaQFmkxgFJaPEPE0jsW6SnKLH0=; b=ys4AEhLuXqvjzDLVJU6dn5aPnEILFJ8intHl3oa8kIx3aGQfqZ0P7F6vlyI3xl0AZmzmoo DPiweUkA7IMUDG52J4pLOZ3G2RifSy2w8D/WSLyDV/O0FHddeXTMgMOd2jFjAyUqqTAg2R JoDurAUakYvm5pTwUMpWo0sO1NA3E8rTKaDq+bdiuVoJzaIkGSKJIW+wdBYAYV+6pbvrzS yFMi1rcA/VQhfU/z6lDqEYoUoTN4z14BeNP1+F2zBiqQSMjepAksRsxZU/rx/gY8EkGkHk 0pOnxoWpcNAFU6rzvX96Ag8/lKf89jLqQeJWnfZhEnIaW79GLdj4NqWDxla1hA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1776970094; a=rsa-sha256; cv=none; b=lg8mbnm+PoyNj9pCDvl1/jMW0qNUlgZ3nbPuZYC4t3SlbMrMeGSjoHhhGOn1sf61jdJz4u Apjyhs04Z7LcqcIvit+o8eA1sGz9zPCsxpYLwzc4AWAuZVuqsPnl0D3BXZWSu7MED3HoKk ZW0KQoXssPpspx/+t9NKVXnp+eu99Dcb20/QefsGvf8I7sHPYJIS7HeA+3g2hvpxSpISVm n/+QdSBKlk95c+ytF9khWJiTeyB4FxIU9iP4hOJ0kma5PYFRxhh9pv+birr4MPqLHQm8ZO w0N1K8ZQGUTcjhVhsncd8h8erRuH6RWi7Htzq2M40we0X95ScZzwaXxggWeloQ== 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=1776970094; 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=pWV0h92KbmoMjo47blaQFmkxgFJaPEPE0jsW6SnKLH0=; b=kxUsQm9DrN6OWVWvgZQ7tadjEaLQTQM/9EwGi79MK5O/OhOLbibf5/rriAKQktg6usk80A IaIRHMG98T5QDaJR0aWFElriUR73XhzLFK1R7WX0w5VoHvFyLDRx1O49YsAJLeuzJlypRP zPoLLV74mjwPvvWjg9kLWOlCHCx1+o1H5UokFyWZilOTMjM+giwR51gH7NHTS/6UFbu03l wDcaW5zDFRJQfUgY04MJloxldnKNP5rebL1HCiISqOJnFiH8AttGk4n4FT3LOFTIwqVzek juM5/FcOFr/hYIoQ8NONK68/9j3HzHTXyODCdB53efnLtSJCSHdFtoRKLMBr/A== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4g1lTp30wQzD1h for ; Thu, 23 Apr 2026 18:48:14 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 47d5a by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 23 Apr 2026 18:48:09 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kyle Evans Subject: git: 0faa88f26c23 - main - kern: vfs: add MAC checks for mount/unmount/update 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 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kevans X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 0faa88f26c239b19ea543309f2c70384438eae73 Auto-Submitted: auto-generated Date: Thu, 23 Apr 2026 18:48:09 +0000 Message-Id: <69ea6969.47d5a.1dc7dd46@gitrepo.freebsd.org> The branch main has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=0faa88f26c239b19ea543309f2c70384438eae73 commit 0faa88f26c239b19ea543309f2c70384438eae73 Author: Kyle Evans AuthorDate: 2026-04-23 18:47:09 +0000 Commit: Kyle Evans CommitDate: 2026-04-23 18:47:09 +0000 kern: vfs: add MAC checks for mount/unmount/update The unmount check is straightforward and only really needs the struct mount and flags used, in case a MAC policy wants to reject force-unmounts or do special handling for FSID-based unmounts. The mount check offers as much information as I think might be of interest to a MAC policy: the vnode to be mounted on, vfsconf, and applicable mount options. XNU also has a later version that just takes a struct mount for everything that VFS_MOUNT() has to offer, but my draft policy doesn't need any of that. It also doesn't really need the unmount check, but it seems reasonable to add it while I'm here. The update check similarly passes the flags/options for the operation, along with the struct mount and label. Reviewed by: kib, olce Differential Revision: https://reviews.freebsd.org/D55601 --- sys/kern/vfs_mount.c | 25 +++++++++++++++++++- sys/security/mac/mac_framework.h | 7 ++++++ sys/security/mac/mac_policy.h | 12 ++++++++++ sys/security/mac/mac_vfs.c | 50 ++++++++++++++++++++++++++++++++++++++++ sys/security/mac_stub/mac_stub.c | 28 ++++++++++++++++++++++ sys/security/mac_test/mac_test.c | 37 +++++++++++++++++++++++++++++ 6 files changed, 158 insertions(+), 1 deletion(-) diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 383ccf98c10e..ddc5a1b70887 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -1152,6 +1152,17 @@ vfs_domount_first( error = VOP_GETATTR(vp, &va, td->td_ucred); if (error == 0 && va.va_uid != td->td_ucred->cr_uid) error = priv_check_cred(td->td_ucred, PRIV_VFS_ADMIN); +#ifdef MAC + /* + * XXX XNU also has a check_mount_late variant, which takes the + * struct mount instead and gives MAC visibility into, e.g., + * f_mntfromname and other facts. + */ + if (error == 0) { + error = mac_mount_check_mount(td->td_ucred, vp, vfsp, + optlist, fsflags); + } +#endif if (error == 0) error = vinvalbuf(vp, V_SAVE, 0, 0); if (vfsp->vfc_flags & VFCF_FILEMOUNT) { @@ -1371,6 +1382,12 @@ vfs_domount_update( error = 0; vfs_suser_failed = true; } +#ifdef MAC + if (error == 0) { + error = mac_mount_check_update(td->td_ucred, mp, optlist, + fsflags); + } +#endif if (error != 0) { vput(vp); return (error); @@ -1750,7 +1767,6 @@ kern_unmount(struct thread *td, const char *path, uint64_t flags) if (error) return (error); } - if (flags & MNT_BYFSID) { fsidbuf = malloc(MNAMELEN, M_TEMP, M_WAITOK); error = copyinstr(path, fsidbuf, MNAMELEN, NULL); @@ -1818,6 +1834,13 @@ kern_unmount(struct thread *td, const char *path, uint64_t flags) vfs_rel(mp); return (EINVAL); } +#ifdef MAC + error = mac_mount_check_unmount(td->td_ucred, mp, flags); + if (error != 0) { + vfs_rel(mp); + return (error); + } +#endif error = dounmount(mp, flags, td); return (error); } diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h index 5e13434e5ecc..09e5c96c7885 100644 --- a/sys/security/mac/mac_framework.h +++ b/sys/security/mac/mac_framework.h @@ -86,6 +86,7 @@ struct thread; struct timespec; struct ucred; struct vattr; +struct vfsconf; struct vfsoptlist; struct vnode; struct vop_setlabel_args; @@ -248,6 +249,12 @@ int mac_mount_check_stat(struct ucred *cred, struct mount *mp); void mac_mount_create(struct ucred *cred, struct mount *mp); void mac_mount_destroy(struct mount *); void mac_mount_init(struct mount *); +int mac_mount_check_mount(struct ucred *cred, struct vnode *vp, + struct vfsconf *, struct vfsoptlist **optlist, uint64_t fsflags); +int mac_mount_check_update(struct ucred *cred, struct mount *mp, + struct vfsoptlist **optlist, uint64_t fsflags); +int mac_mount_check_unmount(struct ucred *cred, struct mount *mp, + uint64_t flags); void mac_netinet_arp_send(struct ifnet *ifp, struct mbuf *m); void mac_netinet_firewall_reply(struct mbuf *mrecv, struct mbuf *msend); diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h index a080d8cc4b8b..03c0ea2f8550 100644 --- a/sys/security/mac/mac_policy.h +++ b/sys/security/mac/mac_policy.h @@ -101,6 +101,7 @@ struct sysctl_req; struct thread; struct ucred; struct vattr; +struct vfsconf; struct vfsoptlist; struct vnode; @@ -295,6 +296,14 @@ typedef void (*mpo_mount_create_t)(struct ucred *cred, struct mount *mp, struct label *mplabel); typedef void (*mpo_mount_destroy_label_t)(struct label *label); typedef void (*mpo_mount_init_label_t)(struct label *label); +typedef int (*mpo_mount_check_mount_t)(struct ucred *cred, struct vnode *vp, + struct label *vplabel, struct vfsconf *vfsp, + struct vfsoptlist **optlist, uint64_t fsflags); +typedef int (*mpo_mount_check_update_t)(struct ucred *cred, + struct mount *mp, struct label *mplabel, + struct vfsoptlist **optlist, uint64_t fsflags); +typedef int (*mpo_mount_check_unmount_t)(struct ucred *cred, + struct mount *mp, struct label *mplabel, uint64_t flags); typedef void (*mpo_netinet_arp_send_t)(struct ifnet *ifp, struct label *ifplabel, struct mbuf *m, @@ -846,6 +855,9 @@ struct mac_policy_ops { mpo_mount_create_t mpo_mount_create; mpo_mount_destroy_label_t mpo_mount_destroy_label; mpo_mount_init_label_t mpo_mount_init_label; + mpo_mount_check_mount_t mpo_mount_check_mount; + mpo_mount_check_update_t mpo_mount_check_update; + mpo_mount_check_unmount_t mpo_mount_check_unmount; mpo_netinet_arp_send_t mpo_netinet_arp_send; mpo_netinet_firewall_reply_t mpo_netinet_firewall_reply; diff --git a/sys/security/mac/mac_vfs.c b/sys/security/mac/mac_vfs.c index dc2bfa7c643b..2b88742c5c8e 100644 --- a/sys/security/mac/mac_vfs.c +++ b/sys/security/mac/mac_vfs.c @@ -123,6 +123,56 @@ mac_mount_init(struct mount *mp) mp->mnt_label = NULL; } +/* + * SDT doesn't have a PROBE7 version anymore, so we just drop the label. + */ +MAC_CHECK_PROBE_DEFINE5(mount_check_mount, "struct ucred *", + "struct vnode *", "struct vfsconf *", + "struct vfsoptlist **", "uint64_t"); +int +mac_mount_check_mount(struct ucred *cred, struct vnode *vp, + struct vfsconf *vfsp, struct vfsoptlist **optlist, uint64_t fsflags) +{ + int error; + + MAC_POLICY_CHECK(mount_check_mount, cred, vp, vp->v_label, vfsp, + optlist, fsflags); + MAC_CHECK_PROBE5(mount_check_mount, error, cred, vp, vfsp, optlist, + fsflags); + + return (error); +} + +MAC_CHECK_PROBE_DEFINE5(mount_check_update, "struct ucred *", + "struct mount *", "struct label *", "struct vfsoptlist **", "uint64_t"); +int +mac_mount_check_update(struct ucred *cred, struct mount *mp, + struct vfsoptlist **optlist, uint64_t fsflags) +{ + int error; + + MAC_POLICY_CHECK(mount_check_update, cred, mp, mp->mnt_label, + optlist, fsflags); + MAC_CHECK_PROBE5(mount_check_update, error, cred, mp, mp->mnt_label, + optlist, fsflags); + + return (error); +} + +MAC_CHECK_PROBE_DEFINE4(mount_check_unmount, "struct ucred *", + "struct mount *", "struct label *", "uint64_t"); +int +mac_mount_check_unmount(struct ucred *cred, struct mount *mp, uint64_t flags) +{ + int error; + + MAC_POLICY_CHECK(mount_check_unmount, cred, mp, mp->mnt_label, flags); + MAC_CHECK_PROBE4(mount_check_unmount, error, cred, mp, mp->mnt_label, + flags); + + return (error); +} + struct label * mac_vnode_label_alloc(void) { diff --git a/sys/security/mac_stub/mac_stub.c b/sys/security/mac_stub/mac_stub.c index 1e1220300259..299950e95ea7 100644 --- a/sys/security/mac_stub/mac_stub.c +++ b/sys/security/mac_stub/mac_stub.c @@ -574,6 +574,31 @@ stub_mount_create(struct ucred *cred, struct mount *mp, } +static int +stub_mount_check_mount(struct ucred *cred, struct vnode *vp, + struct label *vplabel, struct vfsconf *vfsconf, + struct vfsoptlist **optlist, uint64_t fsflags) +{ + + return (0); +} + +static int +stub_mount_check_update(struct ucred *cred, struct mount *mp, + struct label *mplabel, struct vfsoptlist **optlist, uint64_t fsflags) +{ + + return (0); +} + +static int +stub_mount_check_unmount(struct ucred *cred, struct mount *mp, + struct label *mplabel, uint64_t flags) +{ + + return (0); +} + static void stub_netinet_arp_send(struct ifnet *ifp, struct label *iflpabel, struct mbuf *m, struct label *mlabel) @@ -1864,6 +1889,9 @@ static struct mac_policy_ops stub_ops = .mpo_mount_create = stub_mount_create, .mpo_mount_destroy_label = stub_destroy_label, .mpo_mount_init_label = stub_init_label, + .mpo_mount_check_mount = stub_mount_check_mount, + .mpo_mount_check_update = stub_mount_check_update, + .mpo_mount_check_unmount = stub_mount_check_unmount, .mpo_netinet_arp_send = stub_netinet_arp_send, .mpo_netinet_firewall_reply = stub_netinet_firewall_reply, diff --git a/sys/security/mac_test/mac_test.c b/sys/security/mac_test/mac_test.c index f16073cfdf72..0879b03bb14f 100644 --- a/sys/security/mac_test/mac_test.c +++ b/sys/security/mac_test/mac_test.c @@ -1078,6 +1078,40 @@ test_mount_init_label(struct label *label) COUNTER_INC(mount_init_label); } +COUNTER_DECL(mount_check_mount); +static int +test_mount_check_mount(struct ucred *cred, struct vnode *vp, + struct label *vplabel, struct vfsconf *vfsconf, + struct vfsoptlist **optlist, uint64_t fsflags) +{ + + LABEL_CHECK(vplabel, MAGIC_VNODE); + COUNTER_INC(mount_check_mount); + return (0); +} + +COUNTER_DECL(mount_check_update); +static int +test_mount_check_update(struct ucred *cred, struct mount *mp, + struct label *mplabel, struct vfsoptlist **optlist, uint64_t fsflags) +{ + + LABEL_CHECK(mplabel, MAGIC_MOUNT); + COUNTER_INC(mount_check_update); + return (0); +} + +COUNTER_DECL(mount_check_unmount); +static int +test_mount_check_unmount(struct ucred *cred, struct mount *mp, + struct label *mplabel, uint64_t flags) +{ + + LABEL_CHECK(mplabel, MAGIC_MOUNT); + COUNTER_INC(mount_check_unmount); + return (0); +} + COUNTER_DECL(netinet_arp_send); static void test_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel, @@ -3323,6 +3357,9 @@ static struct mac_policy_ops test_ops = .mpo_mount_create = test_mount_create, .mpo_mount_destroy_label = test_mount_destroy_label, .mpo_mount_init_label = test_mount_init_label, + .mpo_mount_check_mount = test_mount_check_mount, + .mpo_mount_check_update = test_mount_check_update, + .mpo_mount_check_unmount = test_mount_check_unmount, .mpo_netinet_arp_send = test_netinet_arp_send, .mpo_netinet_fragment = test_netinet_fragment,