Date: Thu, 23 Apr 2026 18:48:09 +0000 From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 0faa88f26c23 - main - kern: vfs: add MAC checks for mount/unmount/update Message-ID: <69ea6969.47d5a.1dc7dd46@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=0faa88f26c239b19ea543309f2c70384438eae73 commit 0faa88f26c239b19ea543309f2c70384438eae73 Author: Kyle Evans <kevans@FreeBSD.org> AuthorDate: 2026-04-23 18:47:09 +0000 Commit: Kyle Evans <kevans@FreeBSD.org> 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,home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69ea6969.47d5a.1dc7dd46>
