diff --git a/sys/conf/files b/sys/conf/files index 53978aadd25f..8aec70da9ed8 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -829,7 +829,6 @@ fs/procfs/procfs_ctl.c optional procfs fs/procfs/procfs_dbregs.c optional procfs fs/procfs/procfs_fpregs.c optional procfs fs/procfs/procfs_ioctl.c optional procfs -fs/procfs/procfs_mac.c optional procfs fs/procfs/procfs_map.c optional procfs fs/procfs/procfs_mem.c optional procfs fs/procfs/procfs_note.c optional procfs diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index 869a20f9b6c8..f7b99d500fb1 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -167,7 +167,7 @@ loop: de->de_vnode = vp; vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); #ifdef MAC - mac_create_devfs_vnode(de, vp); + mac_associate_vnode_devfs(mp, de, vp); #endif *vpp = vp; return (0); diff --git a/sys/fs/procfs/procfs.c b/sys/fs/procfs/procfs.c index e99653a1b2ba..f6cab6a39b0e 100644 --- a/sys/fs/procfs/procfs.c +++ b/sys/fs/procfs/procfs.c @@ -153,7 +153,6 @@ procfs_init(PFS_INIT_ARGS) dir = pfs_create_dir(root, "pid", procfs_attr, NULL, PFS_PROCDEP); - dir->pn_refreshlabel = procfs_piddir_refreshlabel; pfs_create_file(dir, "cmdline", procfs_doproccmdline, NULL, NULL, PFS_RD); pfs_create_file(dir, "ctl", procfs_doprocctl, diff --git a/sys/fs/procfs/procfs.h b/sys/fs/procfs/procfs.h index 61f6e9540156..4baaf5059d19 100644 --- a/sys/fs/procfs/procfs.h +++ b/sys/fs/procfs/procfs.h @@ -61,9 +61,6 @@ int procfs_close(PFS_CLOSE_ARGS); /* Attributes */ int procfs_attr(PFS_ATTR_ARGS); -/* MAC */ -int procfs_piddir_refreshlabel(PFS_REFRESHLABEL_ARGS); - /* Visibility */ int procfs_notsystem(PFS_VIS_ARGS); int procfs_candebug(PFS_VIS_ARGS); diff --git a/sys/fs/procfs/procfs_mac.c b/sys/fs/procfs/procfs_mac.c deleted file mode 100644 index ea5c9f5306ac..000000000000 --- a/sys/fs/procfs/procfs_mac.c +++ /dev/null @@ -1,68 +0,0 @@ -/*- - * Copyright (c) 2002 Network Associates Technology, Inc. - * All rights reserved. - * - * This software was developed in part by NAI Labs, the Security Research - * Division of Network Associates, Inc. under DARPA/SPAWAR contract - * N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS research program. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the authors may not be used to endorse or promote - * products derived from this software without specific prior written - * permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include "opt_mac.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -int -procfs_piddir_refreshlabel(PFS_REFRESHLABEL_ARGS) -{ -#ifdef MAC - - if (p == NULL) - mac_update_vnode_from_mount(vp, vp->v_mount); - else { - PROC_LOCK(p); - mac_update_procfsvnode(vp, p->p_ucred); - PROC_UNLOCK(p); - } - - return (0); -#else - return (EOPNOTSUPP); -#endif -} diff --git a/sys/fs/pseudofs/pseudofs.h b/sys/fs/pseudofs/pseudofs.h index c7a64dd99909..2b9d01b1e515 100644 --- a/sys/fs/pseudofs/pseudofs.h +++ b/sys/fs/pseudofs/pseudofs.h @@ -144,15 +144,6 @@ typedef int (*pfs_ioctl_t)(PFS_IOCTL_ARGS); struct ucred; typedef int (*pfs_getextattr_t)(PFS_GETEXTATTR_ARGS); -/* - * Getlabel callback - */ -#define PFS_REFRESHLABEL_ARGS \ - struct thread *td, struct proc *p, struct vnode *vp, \ - struct pfs_node *pn, struct ucred *cred -struct mac; -typedef int (*pfs_refreshlabel_t)(PFS_REFRESHLABEL_ARGS); - /* * Last-close callback */ @@ -194,7 +185,6 @@ struct pfs_node { pfs_attr_t pn_attr; pfs_vis_t pn_vis; pfs_getextattr_t pn_getextattr; - pfs_refreshlabel_t pn_refreshlabel; void *pn_data; int pn_flags; diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c index 932adc0361ee..b797aeb408f0 100644 --- a/sys/fs/pseudofs/pseudofs_vnops.c +++ b/sys/fs/pseudofs/pseudofs_vnops.c @@ -28,8 +28,6 @@ * $FreeBSD$ */ -#include "opt_mac.h" - #include #include #include @@ -37,7 +35,6 @@ #include #include #include -#include #include #include #include @@ -732,50 +729,6 @@ pfs_reclaim(struct vop_reclaim_args *va) return (pfs_vncache_free(va->a_vp)); } -#ifdef MAC -/* - * Refresh the vnode label as appropriate for the pseudo-file system. - */ -static int -pfs_refreshlabel(struct vop_refreshlabel_args *va) -{ - struct vnode *vn = va->a_vp; - struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; - struct pfs_node *pn = pvd->pvd_pn; - struct proc *proc = NULL; - int error; - - PFS_TRACE((pd->pn_name)); - - if (pn->pn_refreshlabel == NULL) { - mac_update_vnode_from_mount(vn, vn->v_mount); - return (0); - } - - /* - * This is necessary because either process' privileges may - * have changed since the last open() call. - */ - if (!pfs_visible(curthread, pn, pvd->pvd_pid)) - PFS_RETURN (EIO); - - /* XXX duplicate bits of pfs_visible() */ - if (pvd->pvd_pid != NO_PID) { - if ((proc = pfind(pvd->pvd_pid)) == NULL) - PFS_RETURN (EIO); - _PHOLD(proc); - PROC_UNLOCK(proc); - } - - error = (pn->pn_refreshlabel)(curthread, proc, vn, pn, va->a_cred); - - if (proc != NULL) - PRELE(proc); - - PFS_RETURN (error); -} -#endif - /* * Set attributes */ diff --git a/sys/kern/kern_mac.c b/sys/kern/kern_mac.c index 78bc485c3863..2ff4162fbfb1 100644 --- a/sys/kern/kern_mac.c +++ b/sys/kern/kern_mac.c @@ -115,6 +115,12 @@ SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, */ static int mac_late = 0; +/* + * Warn about EA transactions only the first time they happen. + * Weak coherency, no locking. + */ +static int ea_warn_once = 0; + static int mac_enforce_fs = 1; SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); @@ -145,23 +151,12 @@ SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); -static int mac_label_size = sizeof(struct oldmac); -SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, - &mac_label_size, 0, "Pre-compiled MAC label size"); - static int mac_cache_fslabel_in_vnode = 1; SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); TUNABLE_INT("security.mac.cache_fslabel_in_vnode", &mac_cache_fslabel_in_vnode); -static int mac_vnode_label_cache_hits = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, - &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); -static int mac_vnode_label_cache_misses = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, - &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); - static int mac_mmap_revocation = 1; SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " @@ -214,12 +209,9 @@ SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, #endif static int error_select(int error1, int error2); -static int mac_externalize_vnode_oldmac(struct label *label, - struct oldmac *extmac); static int mac_policy_register(struct mac_policy_conf *mpc); static int mac_policy_unregister(struct mac_policy_conf *mpc); -static int mac_stdcreatevnode_ea(struct vnode *vp); static void mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot); static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, @@ -227,6 +219,10 @@ static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, static void mac_destroy_socket_label(struct label *label); +static int mac_setlabel_vnode_extattr(struct ucred *cred, + struct vnode *vp, struct label *intlabel); + + MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); @@ -623,10 +619,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_externalize_vnode_label = mpe->mpe_function; break; - case MAC_EXTERNALIZE_VNODE_OLDMAC: - mpc->mpc_ops->mpo_externalize_vnode_oldmac = - mpe->mpe_function; - break; case MAC_INTERNALIZE_CRED_LABEL: mpc->mpc_ops->mpo_internalize_cred_label = mpe->mpe_function; @@ -663,14 +655,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_create_devfs_vnode = mpe->mpe_function; break; - case MAC_STDCREATEVNODE_EA: - mpc->mpc_ops->mpo_stdcreatevnode_ea = - mpe->mpe_function; - break; - case MAC_CREATE_VNODE: - mpc->mpc_ops->mpo_create_vnode = - mpe->mpe_function; - break; case MAC_CREATE_MOUNT: mpc->mpc_ops->mpo_create_mount = mpe->mpe_function; @@ -687,20 +671,24 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_update_devfsdirent = mpe->mpe_function; break; - case MAC_UPDATE_PROCFSVNODE: - mpc->mpc_ops->mpo_update_procfsvnode = + case MAC_ASSOCIATE_VNODE_DEVFS: + mpc->mpc_ops->mpo_associate_vnode_devfs = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTATTR: - mpc->mpc_ops->mpo_update_vnode_from_extattr = + case MAC_ASSOCIATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_associate_vnode_extattr = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: - mpc->mpc_ops->mpo_update_vnode_from_externalized = + case MAC_ASSOCIATE_VNODE_SINGLELABEL: + mpc->mpc_ops->mpo_associate_vnode_singlelabel = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_MOUNT: - mpc->mpc_ops->mpo_update_vnode_from_mount = + case MAC_CREATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_create_vnode_extattr = + mpe->mpe_function; + break; + case MAC_SETLABEL_VNODE_EXTATTR: + mpc->mpc_ops->mpo_setlabel_vnode_extattr = mpe->mpe_function; break; case MAC_CREATE_MBUF_FROM_SOCKET: @@ -1379,7 +1367,7 @@ mac_init_socket(struct socket *socket, int flag) return (error); } -static void +void mac_init_vnode_label(struct label *label) { @@ -1536,7 +1524,7 @@ mac_destroy_socket(struct socket *socket) mac_destroy_socket_peer_label(&socket->so_peerlabel); } -static void +void mac_destroy_vnode_label(struct label *label) { @@ -1561,7 +1549,7 @@ mac_copy_pipe_label(struct label *src, struct label *dest) MAC_PERFORM(copy_pipe_label, src, dest); } -static void +void mac_copy_vnode_label(struct label *src, struct label *dest) { @@ -1644,16 +1632,6 @@ mac_externalize_vnode_label(struct label *label, char *elements, return (error); } -static int -mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(externalize_vnode_oldmac, label, extmac); - - return (error); -} - static int mac_internalize_cred_label(struct label *label, char *string) { @@ -1753,276 +1731,118 @@ mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) } void -mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) +mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, + struct vnode *vp) { - MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); + MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, + &de->de_label, vp, &vp->v_label); } -/* - * Support callout for policies that manage their own externalization - * using extended attributes. - */ -static int -mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) +int +mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) { int error; - MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, - &mp->mnt_fslabel); + ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); + + MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, + &vp->v_label); return (error); } -/* - * Given an externalized mac label, internalize it and stamp it on a - * vnode. - */ -static int -mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); - - return (error); -} - -/* - * Call out to individual policies to update the label in a vnode from - * the mountpoint. - */ void -mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) +mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) { - MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, - &mp->mnt_fslabel); - - ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); - if (mac_cache_fslabel_in_vnode) - vp->v_vflag |= VV_CACHEDLABEL; + MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, + &vp->v_label); } -/* - * Implementation of VOP_REFRESHLABEL() that relies on extended attributes - * to store label data. Can be referenced by filesystems supporting - * extended attributes. - */ int -vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) +mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { - struct vnode *vp = ap->a_vp; - struct oldmac extmac; - int buflen, error; + int error; - ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); + ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); + ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); - /* - * Call out to external policies first. Order doesn't really - * matter, as long as failure of one assures failure of all. - */ - error = mac_update_vnode_from_extattr(vp, vp->v_mount); - if (error) - return (error); - - buflen = sizeof(extmac); - error = vn_extattr_get(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, - (char *)&extmac, curthread); - switch (error) { - case 0: - /* Got it */ - break; - - case ENOATTR: - /* - * Use the label from the mount point. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - - case EOPNOTSUPP: - default: - /* Fail horribly. */ - return (error); - } - - if (buflen != sizeof(extmac)) - error = EPERM; /* Fail very closed. */ - if (error == 0) - error = mac_update_vnode_from_externalized(vp, &extmac); - if (error == 0) - vp->v_vflag |= VV_CACHEDLABEL; - else { - struct vattr va; - - printf("Corrupted label on %s", - vp->v_mount->mnt_stat.f_mntonname); - if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) - printf(" inum %ld", va.va_fileid); -#ifdef MAC_DEBUG - if (mac_debug_label_fallback) { - printf(", falling back.\n"); - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - } else { -#endif - printf(".\n"); - error = EPERM; -#ifdef MAC_DEBUG + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; } -#endif + } else if (error) + return (error); + + MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, + dvp, &dvp->v_label, vp, &vp->v_label, cnp); + + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); + return (error); } + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); + + if (error == EOPNOTSUPP) + error = 0; /* XXX */ + return (error); } -/* - * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle - * the labeling activity outselves. Filesystems should be careful not - * to change their minds regarding whether they support vop_refreshlabel() - * for a vnode or not. Don't cache the vnode here, allow the file - * system code to determine if it's safe to cache. If we update from - * the mount, don't cache since a change to the mount label should affect - * all vnodes. - */ static int -vn_refreshlabel(struct vnode *vp, struct ucred *cred) +mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *intlabel) { int error; - ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); + ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); - if (vp->v_mount == NULL) { -/* - Eventually, we probably want to special-case refreshing - of deadfs vnodes, and if there's a lock-free race somewhere, - that case might be handled here. + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; + } + } else if (error) + return (error); - mac_update_vnode_deadfs(vp); - return (0); - */ - /* printf("vn_refreshlabel: null v_mount\n"); */ - if (vp->v_type != VNON) - printf( - "vn_refreshlabel: null v_mount with non-VNON\n"); - return (EBADF); - } + MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); - if (vp->v_vflag & VV_CACHEDLABEL) { - mac_vnode_label_cache_hits++; - return (0); - } else - mac_vnode_label_cache_misses++; - - if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - } - - error = VOP_REFRESHLABEL(vp, cred, curthread); - switch (error) { - case EOPNOTSUPP: - /* - * If labels are not supported on this vnode, fall back to - * the label in the mount and propagate it to the vnode. - * There should probably be some sort of policy/flag/decision - * about doing this. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - default: + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); return (error); } -} -/* - * Helper function for file systems using the vop_std*_ea() calls. This - * function must be called after EA service is available for the vnode, - * but before it's hooked up to the namespace so that the node persists - * if there's a crash, or before it can be accessed. On successful - * commit of the label to disk (etc), do cache the label. - */ -int -vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) -{ - struct oldmac extmac; - int error; + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); - ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); - if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(tvp, tvp->v_mount); - } else { - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); + if (error == EOPNOTSUPP) + error = 0; /* XXX */ - /* - * Stick the label in the vnode. Then try to write to - * disk. If we fail, return a failure to abort the - * create operation. Really, this failure shouldn't - * happen except in fairly unusual circumstances (out - * of disk, etc). - */ - mac_create_vnode(cred, dvp, tvp); - - error = mac_stdcreatevnode_ea(tvp); - if (error) - return (error); - - /* - * XXX: Eventually this will go away and all policies will - * directly manage their extended attributes. - */ - error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac); - if (error) - return (error); - - error = vn_extattr_set(tvp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); - if (error == 0) - tvp->v_vflag |= VV_CACHEDLABEL; - else { -#if 0 - /* - * In theory, we could have fall-back behavior here. - * It would probably be incorrect. - */ -#endif - return (error); - } - } - - return (0); + return (error); } void mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) { - int error; ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); - error = vn_refreshlabel(vp, old); - if (error) { - printf("mac_execve_transition: vn_refreshlabel returned %d\n", - error); - printf("mac_execve_transition: using old vnode label\n"); - } - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); } int mac_execve_will_transition(struct ucred *old, struct vnode *vp) { - int error, result; - - error = vn_refreshlabel(vp, old); - if (error) - return (error); + int result; result = 0; MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); @@ -2040,10 +1860,6 @@ mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); return (error); } @@ -2058,10 +1874,6 @@ mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); return (error); } @@ -2076,10 +1888,6 @@ mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); return (error); } @@ -2095,10 +1903,6 @@ mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); return (error); } @@ -2115,13 +1919,6 @@ mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2138,10 +1935,6 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); return (error); } @@ -2156,9 +1949,6 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); return (error); @@ -2174,10 +1964,6 @@ mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); return (error); } @@ -2193,10 +1979,6 @@ mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2214,14 +1996,6 @@ mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2238,10 +2012,6 @@ mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); return (error); } @@ -2256,10 +2026,6 @@ mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); return (error); } @@ -2290,10 +2056,6 @@ mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); return (error); } @@ -2308,10 +2070,6 @@ mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); return (error); } @@ -2327,10 +2085,6 @@ mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, &vp->v_label); @@ -2348,10 +2102,6 @@ mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, &vp->v_label); @@ -2368,10 +2118,6 @@ mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); return (error); } @@ -2386,10 +2132,6 @@ mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); return (error); } @@ -2402,10 +2144,6 @@ mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); return (error); @@ -2423,13 +2161,6 @@ mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2447,14 +2178,6 @@ mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - if (vp != NULL) { - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - } MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, vp != NULL ? &vp->v_label : NULL, samedir, cnp); return (error); @@ -2470,10 +2193,6 @@ mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); return (error); } @@ -2489,10 +2208,6 @@ mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); return (error); } @@ -2508,10 +2223,6 @@ mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2527,10 +2238,6 @@ mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); return (error); } @@ -2545,10 +2252,6 @@ mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); return (error); } @@ -2564,10 +2267,6 @@ mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); return (error); } @@ -2583,10 +2282,6 @@ mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, mtime); return (error); @@ -2603,10 +2298,6 @@ mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, &vp->v_label); return (error); @@ -2622,10 +2313,6 @@ mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label); return (error); } @@ -2641,10 +2328,6 @@ mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, &vp->v_label); @@ -3344,7 +3027,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3352,7 +3034,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_ifnet_label(&ifnet->if_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3382,7 +3063,6 @@ mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3444,16 +3124,6 @@ mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, &de->de_label); } -static int -mac_stdcreatevnode_ea(struct vnode *vp) -{ - int error; - - MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); - - return (error); -} - void mac_create_devfs_directory(char *dirname, int dirnamelen, struct devfs_dirent *de) @@ -3463,29 +3133,6 @@ mac_create_devfs_directory(char *dirname, int dirnamelen, &de->de_label); } -/* - * When a new vnode is created, this call will initialize its label. - */ -void -mac_create_vnode(struct ucred *cred, struct vnode *parent, - struct vnode *child) -{ - int error; - - ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); - ASSERT_VOP_LOCKED(child, "mac_create_vnode"); - - error = vn_refreshlabel(parent, cred); - if (error) { - printf("mac_create_vnode: vn_refreshlabel returned %d\n", - error); - printf("mac_create_vnode: using old vnode label\n"); - } - - MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, - &child->v_label); -} - int mac_setsockopt_label_set(struct ucred *cred, struct socket *so, struct mac *mac) @@ -3499,7 +3146,6 @@ mac_setsockopt_label_set(struct ucred *cred, struct socket *so, return (error); buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3554,7 +3200,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3562,7 +3207,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_label(&so->so_label, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3586,7 +3230,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3594,7 +3237,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_peer_label(&so->so_peerlabel, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3616,35 +3258,19 @@ vop_stdsetlabel_ea(struct vop_setlabel_args *ap) { struct vnode *vp = ap->a_vp; struct label *intlabel = ap->a_label; - struct oldmac extmac; int error; ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); - /* - * XXX: Eventually call out to EA check/set calls here. - * Be particularly careful to avoid race conditions, - * consistency problems, and stability problems when - * dealing with multiple EAs. In particular, we require - * the ability to write multiple EAs on the same file in - * a single transaction, which the current EA interface - * does not provide. - */ + if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) + return (EOPNOTSUPP); - error = mac_externalize_vnode_oldmac(intlabel, &extmac); - if (error) - return (error); - - error = vn_extattr_set(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); + error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); if (error) return (error); mac_relabel_vnode(ap->a_cred, vp, intlabel); - vp->v_vflag |= VV_CACHEDLABEL; - return (0); } @@ -3721,7 +3347,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3730,7 +3355,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&tcred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3761,7 +3385,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3769,7 +3392,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&td->td_ucred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3802,7 +3424,6 @@ __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3880,7 +3501,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3888,7 +3508,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ error = fget(td, SCARG(uap, fd), &fp); if (error) @@ -3903,9 +3522,7 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) mac_init_vnode_label(&intlabel); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - error = vn_refreshlabel(vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&vp->v_label, &intlabel); + mac_copy_vnode_label(&vp->v_label, &intlabel); VOP_UNLOCK(vp, 0, td); break; @@ -3974,7 +3591,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3982,7 +3598,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -3991,12 +3606,9 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4034,7 +3646,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -4042,7 +3653,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -4051,12 +3661,9 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4096,7 +3703,6 @@ __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4183,7 +3789,6 @@ __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4240,7 +3845,6 @@ __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index c847563fc7be..dd377fcd1ff3 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -1004,6 +1004,8 @@ getnewvnode(tag, mp, vops, vpp) VI_UNLOCK(vp); #ifdef MAC mac_init_vnode(vp); + if (mp != NULL && (mp->mnt_flag & MNT_MULTILABEL) == 0) + mac_associate_vnode_singlelabel(mp, vp); #endif insmntque(vp, mp); diff --git a/sys/modules/procfs/Makefile b/sys/modules/procfs/Makefile index d4f41b334f98..75e23a0750f5 100644 --- a/sys/modules/procfs/Makefile +++ b/sys/modules/procfs/Makefile @@ -4,13 +4,11 @@ KMOD= procfs SRCS= -SRCS+= opt_mac.h SRCS+= vnode_if.h SRCS+= procfs_ctl.c SRCS+= procfs_dbregs.c SRCS+= procfs_fpregs.c SRCS+= procfs_ioctl.c -SRCS+= procfs_mac.c SRCS+= procfs_map.c SRCS+= procfs_mem.c SRCS+= procfs_note.c diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c index 78bc485c3863..2ff4162fbfb1 100644 --- a/sys/security/mac/mac_framework.c +++ b/sys/security/mac/mac_framework.c @@ -115,6 +115,12 @@ SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, */ static int mac_late = 0; +/* + * Warn about EA transactions only the first time they happen. + * Weak coherency, no locking. + */ +static int ea_warn_once = 0; + static int mac_enforce_fs = 1; SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); @@ -145,23 +151,12 @@ SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); -static int mac_label_size = sizeof(struct oldmac); -SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, - &mac_label_size, 0, "Pre-compiled MAC label size"); - static int mac_cache_fslabel_in_vnode = 1; SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); TUNABLE_INT("security.mac.cache_fslabel_in_vnode", &mac_cache_fslabel_in_vnode); -static int mac_vnode_label_cache_hits = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, - &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); -static int mac_vnode_label_cache_misses = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, - &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); - static int mac_mmap_revocation = 1; SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " @@ -214,12 +209,9 @@ SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, #endif static int error_select(int error1, int error2); -static int mac_externalize_vnode_oldmac(struct label *label, - struct oldmac *extmac); static int mac_policy_register(struct mac_policy_conf *mpc); static int mac_policy_unregister(struct mac_policy_conf *mpc); -static int mac_stdcreatevnode_ea(struct vnode *vp); static void mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot); static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, @@ -227,6 +219,10 @@ static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, static void mac_destroy_socket_label(struct label *label); +static int mac_setlabel_vnode_extattr(struct ucred *cred, + struct vnode *vp, struct label *intlabel); + + MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); @@ -623,10 +619,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_externalize_vnode_label = mpe->mpe_function; break; - case MAC_EXTERNALIZE_VNODE_OLDMAC: - mpc->mpc_ops->mpo_externalize_vnode_oldmac = - mpe->mpe_function; - break; case MAC_INTERNALIZE_CRED_LABEL: mpc->mpc_ops->mpo_internalize_cred_label = mpe->mpe_function; @@ -663,14 +655,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_create_devfs_vnode = mpe->mpe_function; break; - case MAC_STDCREATEVNODE_EA: - mpc->mpc_ops->mpo_stdcreatevnode_ea = - mpe->mpe_function; - break; - case MAC_CREATE_VNODE: - mpc->mpc_ops->mpo_create_vnode = - mpe->mpe_function; - break; case MAC_CREATE_MOUNT: mpc->mpc_ops->mpo_create_mount = mpe->mpe_function; @@ -687,20 +671,24 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_update_devfsdirent = mpe->mpe_function; break; - case MAC_UPDATE_PROCFSVNODE: - mpc->mpc_ops->mpo_update_procfsvnode = + case MAC_ASSOCIATE_VNODE_DEVFS: + mpc->mpc_ops->mpo_associate_vnode_devfs = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTATTR: - mpc->mpc_ops->mpo_update_vnode_from_extattr = + case MAC_ASSOCIATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_associate_vnode_extattr = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: - mpc->mpc_ops->mpo_update_vnode_from_externalized = + case MAC_ASSOCIATE_VNODE_SINGLELABEL: + mpc->mpc_ops->mpo_associate_vnode_singlelabel = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_MOUNT: - mpc->mpc_ops->mpo_update_vnode_from_mount = + case MAC_CREATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_create_vnode_extattr = + mpe->mpe_function; + break; + case MAC_SETLABEL_VNODE_EXTATTR: + mpc->mpc_ops->mpo_setlabel_vnode_extattr = mpe->mpe_function; break; case MAC_CREATE_MBUF_FROM_SOCKET: @@ -1379,7 +1367,7 @@ mac_init_socket(struct socket *socket, int flag) return (error); } -static void +void mac_init_vnode_label(struct label *label) { @@ -1536,7 +1524,7 @@ mac_destroy_socket(struct socket *socket) mac_destroy_socket_peer_label(&socket->so_peerlabel); } -static void +void mac_destroy_vnode_label(struct label *label) { @@ -1561,7 +1549,7 @@ mac_copy_pipe_label(struct label *src, struct label *dest) MAC_PERFORM(copy_pipe_label, src, dest); } -static void +void mac_copy_vnode_label(struct label *src, struct label *dest) { @@ -1644,16 +1632,6 @@ mac_externalize_vnode_label(struct label *label, char *elements, return (error); } -static int -mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(externalize_vnode_oldmac, label, extmac); - - return (error); -} - static int mac_internalize_cred_label(struct label *label, char *string) { @@ -1753,276 +1731,118 @@ mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) } void -mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) +mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, + struct vnode *vp) { - MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); + MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, + &de->de_label, vp, &vp->v_label); } -/* - * Support callout for policies that manage their own externalization - * using extended attributes. - */ -static int -mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) +int +mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) { int error; - MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, - &mp->mnt_fslabel); + ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); + + MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, + &vp->v_label); return (error); } -/* - * Given an externalized mac label, internalize it and stamp it on a - * vnode. - */ -static int -mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); - - return (error); -} - -/* - * Call out to individual policies to update the label in a vnode from - * the mountpoint. - */ void -mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) +mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) { - MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, - &mp->mnt_fslabel); - - ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); - if (mac_cache_fslabel_in_vnode) - vp->v_vflag |= VV_CACHEDLABEL; + MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, + &vp->v_label); } -/* - * Implementation of VOP_REFRESHLABEL() that relies on extended attributes - * to store label data. Can be referenced by filesystems supporting - * extended attributes. - */ int -vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) +mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { - struct vnode *vp = ap->a_vp; - struct oldmac extmac; - int buflen, error; + int error; - ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); + ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); + ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); - /* - * Call out to external policies first. Order doesn't really - * matter, as long as failure of one assures failure of all. - */ - error = mac_update_vnode_from_extattr(vp, vp->v_mount); - if (error) - return (error); - - buflen = sizeof(extmac); - error = vn_extattr_get(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, - (char *)&extmac, curthread); - switch (error) { - case 0: - /* Got it */ - break; - - case ENOATTR: - /* - * Use the label from the mount point. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - - case EOPNOTSUPP: - default: - /* Fail horribly. */ - return (error); - } - - if (buflen != sizeof(extmac)) - error = EPERM; /* Fail very closed. */ - if (error == 0) - error = mac_update_vnode_from_externalized(vp, &extmac); - if (error == 0) - vp->v_vflag |= VV_CACHEDLABEL; - else { - struct vattr va; - - printf("Corrupted label on %s", - vp->v_mount->mnt_stat.f_mntonname); - if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) - printf(" inum %ld", va.va_fileid); -#ifdef MAC_DEBUG - if (mac_debug_label_fallback) { - printf(", falling back.\n"); - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - } else { -#endif - printf(".\n"); - error = EPERM; -#ifdef MAC_DEBUG + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; } -#endif + } else if (error) + return (error); + + MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, + dvp, &dvp->v_label, vp, &vp->v_label, cnp); + + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); + return (error); } + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); + + if (error == EOPNOTSUPP) + error = 0; /* XXX */ + return (error); } -/* - * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle - * the labeling activity outselves. Filesystems should be careful not - * to change their minds regarding whether they support vop_refreshlabel() - * for a vnode or not. Don't cache the vnode here, allow the file - * system code to determine if it's safe to cache. If we update from - * the mount, don't cache since a change to the mount label should affect - * all vnodes. - */ static int -vn_refreshlabel(struct vnode *vp, struct ucred *cred) +mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *intlabel) { int error; - ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); + ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); - if (vp->v_mount == NULL) { -/* - Eventually, we probably want to special-case refreshing - of deadfs vnodes, and if there's a lock-free race somewhere, - that case might be handled here. + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; + } + } else if (error) + return (error); - mac_update_vnode_deadfs(vp); - return (0); - */ - /* printf("vn_refreshlabel: null v_mount\n"); */ - if (vp->v_type != VNON) - printf( - "vn_refreshlabel: null v_mount with non-VNON\n"); - return (EBADF); - } + MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); - if (vp->v_vflag & VV_CACHEDLABEL) { - mac_vnode_label_cache_hits++; - return (0); - } else - mac_vnode_label_cache_misses++; - - if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - } - - error = VOP_REFRESHLABEL(vp, cred, curthread); - switch (error) { - case EOPNOTSUPP: - /* - * If labels are not supported on this vnode, fall back to - * the label in the mount and propagate it to the vnode. - * There should probably be some sort of policy/flag/decision - * about doing this. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - default: + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); return (error); } -} -/* - * Helper function for file systems using the vop_std*_ea() calls. This - * function must be called after EA service is available for the vnode, - * but before it's hooked up to the namespace so that the node persists - * if there's a crash, or before it can be accessed. On successful - * commit of the label to disk (etc), do cache the label. - */ -int -vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) -{ - struct oldmac extmac; - int error; + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); - ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); - if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(tvp, tvp->v_mount); - } else { - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); + if (error == EOPNOTSUPP) + error = 0; /* XXX */ - /* - * Stick the label in the vnode. Then try to write to - * disk. If we fail, return a failure to abort the - * create operation. Really, this failure shouldn't - * happen except in fairly unusual circumstances (out - * of disk, etc). - */ - mac_create_vnode(cred, dvp, tvp); - - error = mac_stdcreatevnode_ea(tvp); - if (error) - return (error); - - /* - * XXX: Eventually this will go away and all policies will - * directly manage their extended attributes. - */ - error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac); - if (error) - return (error); - - error = vn_extattr_set(tvp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); - if (error == 0) - tvp->v_vflag |= VV_CACHEDLABEL; - else { -#if 0 - /* - * In theory, we could have fall-back behavior here. - * It would probably be incorrect. - */ -#endif - return (error); - } - } - - return (0); + return (error); } void mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) { - int error; ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); - error = vn_refreshlabel(vp, old); - if (error) { - printf("mac_execve_transition: vn_refreshlabel returned %d\n", - error); - printf("mac_execve_transition: using old vnode label\n"); - } - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); } int mac_execve_will_transition(struct ucred *old, struct vnode *vp) { - int error, result; - - error = vn_refreshlabel(vp, old); - if (error) - return (error); + int result; result = 0; MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); @@ -2040,10 +1860,6 @@ mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); return (error); } @@ -2058,10 +1874,6 @@ mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); return (error); } @@ -2076,10 +1888,6 @@ mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); return (error); } @@ -2095,10 +1903,6 @@ mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); return (error); } @@ -2115,13 +1919,6 @@ mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2138,10 +1935,6 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); return (error); } @@ -2156,9 +1949,6 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); return (error); @@ -2174,10 +1964,6 @@ mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); return (error); } @@ -2193,10 +1979,6 @@ mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2214,14 +1996,6 @@ mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2238,10 +2012,6 @@ mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); return (error); } @@ -2256,10 +2026,6 @@ mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); return (error); } @@ -2290,10 +2056,6 @@ mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); return (error); } @@ -2308,10 +2070,6 @@ mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); return (error); } @@ -2327,10 +2085,6 @@ mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, &vp->v_label); @@ -2348,10 +2102,6 @@ mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, &vp->v_label); @@ -2368,10 +2118,6 @@ mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); return (error); } @@ -2386,10 +2132,6 @@ mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); return (error); } @@ -2402,10 +2144,6 @@ mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); return (error); @@ -2423,13 +2161,6 @@ mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2447,14 +2178,6 @@ mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - if (vp != NULL) { - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - } MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, vp != NULL ? &vp->v_label : NULL, samedir, cnp); return (error); @@ -2470,10 +2193,6 @@ mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); return (error); } @@ -2489,10 +2208,6 @@ mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); return (error); } @@ -2508,10 +2223,6 @@ mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2527,10 +2238,6 @@ mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); return (error); } @@ -2545,10 +2252,6 @@ mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); return (error); } @@ -2564,10 +2267,6 @@ mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); return (error); } @@ -2583,10 +2282,6 @@ mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, mtime); return (error); @@ -2603,10 +2298,6 @@ mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, &vp->v_label); return (error); @@ -2622,10 +2313,6 @@ mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label); return (error); } @@ -2641,10 +2328,6 @@ mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, &vp->v_label); @@ -3344,7 +3027,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3352,7 +3034,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_ifnet_label(&ifnet->if_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3382,7 +3063,6 @@ mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3444,16 +3124,6 @@ mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, &de->de_label); } -static int -mac_stdcreatevnode_ea(struct vnode *vp) -{ - int error; - - MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); - - return (error); -} - void mac_create_devfs_directory(char *dirname, int dirnamelen, struct devfs_dirent *de) @@ -3463,29 +3133,6 @@ mac_create_devfs_directory(char *dirname, int dirnamelen, &de->de_label); } -/* - * When a new vnode is created, this call will initialize its label. - */ -void -mac_create_vnode(struct ucred *cred, struct vnode *parent, - struct vnode *child) -{ - int error; - - ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); - ASSERT_VOP_LOCKED(child, "mac_create_vnode"); - - error = vn_refreshlabel(parent, cred); - if (error) { - printf("mac_create_vnode: vn_refreshlabel returned %d\n", - error); - printf("mac_create_vnode: using old vnode label\n"); - } - - MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, - &child->v_label); -} - int mac_setsockopt_label_set(struct ucred *cred, struct socket *so, struct mac *mac) @@ -3499,7 +3146,6 @@ mac_setsockopt_label_set(struct ucred *cred, struct socket *so, return (error); buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3554,7 +3200,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3562,7 +3207,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_label(&so->so_label, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3586,7 +3230,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3594,7 +3237,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_peer_label(&so->so_peerlabel, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3616,35 +3258,19 @@ vop_stdsetlabel_ea(struct vop_setlabel_args *ap) { struct vnode *vp = ap->a_vp; struct label *intlabel = ap->a_label; - struct oldmac extmac; int error; ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); - /* - * XXX: Eventually call out to EA check/set calls here. - * Be particularly careful to avoid race conditions, - * consistency problems, and stability problems when - * dealing with multiple EAs. In particular, we require - * the ability to write multiple EAs on the same file in - * a single transaction, which the current EA interface - * does not provide. - */ + if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) + return (EOPNOTSUPP); - error = mac_externalize_vnode_oldmac(intlabel, &extmac); - if (error) - return (error); - - error = vn_extattr_set(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); + error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); if (error) return (error); mac_relabel_vnode(ap->a_cred, vp, intlabel); - vp->v_vflag |= VV_CACHEDLABEL; - return (0); } @@ -3721,7 +3347,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3730,7 +3355,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&tcred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3761,7 +3385,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3769,7 +3392,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&td->td_ucred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3802,7 +3424,6 @@ __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3880,7 +3501,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3888,7 +3508,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ error = fget(td, SCARG(uap, fd), &fp); if (error) @@ -3903,9 +3522,7 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) mac_init_vnode_label(&intlabel); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - error = vn_refreshlabel(vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&vp->v_label, &intlabel); + mac_copy_vnode_label(&vp->v_label, &intlabel); VOP_UNLOCK(vp, 0, td); break; @@ -3974,7 +3591,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3982,7 +3598,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -3991,12 +3606,9 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4034,7 +3646,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -4042,7 +3653,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -4051,12 +3661,9 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4096,7 +3703,6 @@ __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4183,7 +3789,6 @@ __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4240,7 +3845,6 @@ __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h index bcf36e03b21f..cc9552b354bb 100644 --- a/sys/security/mac/mac_framework.h +++ b/sys/security/mac/mac_framework.h @@ -195,6 +195,8 @@ void mac_init_pipe(struct pipe *); int mac_init_mbuf(struct mbuf *m, int flag); void mac_init_mount(struct mount *); void mac_init_vnode(struct vnode *); +void mac_init_vnode_label(struct label *); +void mac_copy_vnode_label(struct label *, struct label *label); void mac_destroy_bpfdesc(struct bpf_d *); void mac_destroy_cred(struct ucred *); void mac_destroy_devfsdirent(struct devfs_dirent *); @@ -205,26 +207,29 @@ void mac_destroy_pipe(struct pipe *); void mac_destroy_mbuf(struct mbuf *); void mac_destroy_mount(struct mount *); void mac_destroy_vnode(struct vnode *); +void mac_destroy_vnode_label(struct label *); /* * Labeling event operations: file system objects, and things that * look a lot like file system objects. */ +void mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, + struct vnode *vp); +int mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp); +void mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp); void mac_create_devfs_device(dev_t dev, struct devfs_dirent *de); void mac_create_devfs_directory(char *dirname, int dirnamelen, struct devfs_dirent *de); void mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, struct devfs_dirent *de); void mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp); -void mac_create_vnode(struct ucred *cred, struct vnode *parent, - struct vnode *child); +int mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct vnode *dvp, struct vnode *vp, struct componentname *cnp); void mac_create_mount(struct ucred *cred, struct mount *mp); void mac_create_root_mount(struct ucred *cred, struct mount *mp); void mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel); void mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp); -void mac_update_procfsvnode(struct vnode *vp, struct ucred *cred); -void mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp); /* * Labeling event operations: IPC objects. @@ -362,9 +367,6 @@ int mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, * Calls to help various file systems implement labeling functionality * using their existing EA implementation. */ -int vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, - struct ucred *cred); -int vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap); int vop_stdsetlabel_ea(struct vop_setlabel_args *ap); #endif /* _KERNEL */ diff --git a/sys/security/mac/mac_internal.h b/sys/security/mac/mac_internal.h index 78bc485c3863..2ff4162fbfb1 100644 --- a/sys/security/mac/mac_internal.h +++ b/sys/security/mac/mac_internal.h @@ -115,6 +115,12 @@ SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, */ static int mac_late = 0; +/* + * Warn about EA transactions only the first time they happen. + * Weak coherency, no locking. + */ +static int ea_warn_once = 0; + static int mac_enforce_fs = 1; SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); @@ -145,23 +151,12 @@ SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); -static int mac_label_size = sizeof(struct oldmac); -SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, - &mac_label_size, 0, "Pre-compiled MAC label size"); - static int mac_cache_fslabel_in_vnode = 1; SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); TUNABLE_INT("security.mac.cache_fslabel_in_vnode", &mac_cache_fslabel_in_vnode); -static int mac_vnode_label_cache_hits = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, - &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); -static int mac_vnode_label_cache_misses = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, - &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); - static int mac_mmap_revocation = 1; SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " @@ -214,12 +209,9 @@ SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, #endif static int error_select(int error1, int error2); -static int mac_externalize_vnode_oldmac(struct label *label, - struct oldmac *extmac); static int mac_policy_register(struct mac_policy_conf *mpc); static int mac_policy_unregister(struct mac_policy_conf *mpc); -static int mac_stdcreatevnode_ea(struct vnode *vp); static void mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot); static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, @@ -227,6 +219,10 @@ static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, static void mac_destroy_socket_label(struct label *label); +static int mac_setlabel_vnode_extattr(struct ucred *cred, + struct vnode *vp, struct label *intlabel); + + MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); @@ -623,10 +619,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_externalize_vnode_label = mpe->mpe_function; break; - case MAC_EXTERNALIZE_VNODE_OLDMAC: - mpc->mpc_ops->mpo_externalize_vnode_oldmac = - mpe->mpe_function; - break; case MAC_INTERNALIZE_CRED_LABEL: mpc->mpc_ops->mpo_internalize_cred_label = mpe->mpe_function; @@ -663,14 +655,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_create_devfs_vnode = mpe->mpe_function; break; - case MAC_STDCREATEVNODE_EA: - mpc->mpc_ops->mpo_stdcreatevnode_ea = - mpe->mpe_function; - break; - case MAC_CREATE_VNODE: - mpc->mpc_ops->mpo_create_vnode = - mpe->mpe_function; - break; case MAC_CREATE_MOUNT: mpc->mpc_ops->mpo_create_mount = mpe->mpe_function; @@ -687,20 +671,24 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_update_devfsdirent = mpe->mpe_function; break; - case MAC_UPDATE_PROCFSVNODE: - mpc->mpc_ops->mpo_update_procfsvnode = + case MAC_ASSOCIATE_VNODE_DEVFS: + mpc->mpc_ops->mpo_associate_vnode_devfs = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTATTR: - mpc->mpc_ops->mpo_update_vnode_from_extattr = + case MAC_ASSOCIATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_associate_vnode_extattr = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: - mpc->mpc_ops->mpo_update_vnode_from_externalized = + case MAC_ASSOCIATE_VNODE_SINGLELABEL: + mpc->mpc_ops->mpo_associate_vnode_singlelabel = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_MOUNT: - mpc->mpc_ops->mpo_update_vnode_from_mount = + case MAC_CREATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_create_vnode_extattr = + mpe->mpe_function; + break; + case MAC_SETLABEL_VNODE_EXTATTR: + mpc->mpc_ops->mpo_setlabel_vnode_extattr = mpe->mpe_function; break; case MAC_CREATE_MBUF_FROM_SOCKET: @@ -1379,7 +1367,7 @@ mac_init_socket(struct socket *socket, int flag) return (error); } -static void +void mac_init_vnode_label(struct label *label) { @@ -1536,7 +1524,7 @@ mac_destroy_socket(struct socket *socket) mac_destroy_socket_peer_label(&socket->so_peerlabel); } -static void +void mac_destroy_vnode_label(struct label *label) { @@ -1561,7 +1549,7 @@ mac_copy_pipe_label(struct label *src, struct label *dest) MAC_PERFORM(copy_pipe_label, src, dest); } -static void +void mac_copy_vnode_label(struct label *src, struct label *dest) { @@ -1644,16 +1632,6 @@ mac_externalize_vnode_label(struct label *label, char *elements, return (error); } -static int -mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(externalize_vnode_oldmac, label, extmac); - - return (error); -} - static int mac_internalize_cred_label(struct label *label, char *string) { @@ -1753,276 +1731,118 @@ mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) } void -mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) +mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, + struct vnode *vp) { - MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); + MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, + &de->de_label, vp, &vp->v_label); } -/* - * Support callout for policies that manage their own externalization - * using extended attributes. - */ -static int -mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) +int +mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) { int error; - MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, - &mp->mnt_fslabel); + ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); + + MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, + &vp->v_label); return (error); } -/* - * Given an externalized mac label, internalize it and stamp it on a - * vnode. - */ -static int -mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); - - return (error); -} - -/* - * Call out to individual policies to update the label in a vnode from - * the mountpoint. - */ void -mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) +mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) { - MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, - &mp->mnt_fslabel); - - ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); - if (mac_cache_fslabel_in_vnode) - vp->v_vflag |= VV_CACHEDLABEL; + MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, + &vp->v_label); } -/* - * Implementation of VOP_REFRESHLABEL() that relies on extended attributes - * to store label data. Can be referenced by filesystems supporting - * extended attributes. - */ int -vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) +mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { - struct vnode *vp = ap->a_vp; - struct oldmac extmac; - int buflen, error; + int error; - ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); + ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); + ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); - /* - * Call out to external policies first. Order doesn't really - * matter, as long as failure of one assures failure of all. - */ - error = mac_update_vnode_from_extattr(vp, vp->v_mount); - if (error) - return (error); - - buflen = sizeof(extmac); - error = vn_extattr_get(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, - (char *)&extmac, curthread); - switch (error) { - case 0: - /* Got it */ - break; - - case ENOATTR: - /* - * Use the label from the mount point. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - - case EOPNOTSUPP: - default: - /* Fail horribly. */ - return (error); - } - - if (buflen != sizeof(extmac)) - error = EPERM; /* Fail very closed. */ - if (error == 0) - error = mac_update_vnode_from_externalized(vp, &extmac); - if (error == 0) - vp->v_vflag |= VV_CACHEDLABEL; - else { - struct vattr va; - - printf("Corrupted label on %s", - vp->v_mount->mnt_stat.f_mntonname); - if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) - printf(" inum %ld", va.va_fileid); -#ifdef MAC_DEBUG - if (mac_debug_label_fallback) { - printf(", falling back.\n"); - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - } else { -#endif - printf(".\n"); - error = EPERM; -#ifdef MAC_DEBUG + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; } -#endif + } else if (error) + return (error); + + MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, + dvp, &dvp->v_label, vp, &vp->v_label, cnp); + + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); + return (error); } + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); + + if (error == EOPNOTSUPP) + error = 0; /* XXX */ + return (error); } -/* - * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle - * the labeling activity outselves. Filesystems should be careful not - * to change their minds regarding whether they support vop_refreshlabel() - * for a vnode or not. Don't cache the vnode here, allow the file - * system code to determine if it's safe to cache. If we update from - * the mount, don't cache since a change to the mount label should affect - * all vnodes. - */ static int -vn_refreshlabel(struct vnode *vp, struct ucred *cred) +mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *intlabel) { int error; - ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); + ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); - if (vp->v_mount == NULL) { -/* - Eventually, we probably want to special-case refreshing - of deadfs vnodes, and if there's a lock-free race somewhere, - that case might be handled here. + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; + } + } else if (error) + return (error); - mac_update_vnode_deadfs(vp); - return (0); - */ - /* printf("vn_refreshlabel: null v_mount\n"); */ - if (vp->v_type != VNON) - printf( - "vn_refreshlabel: null v_mount with non-VNON\n"); - return (EBADF); - } + MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); - if (vp->v_vflag & VV_CACHEDLABEL) { - mac_vnode_label_cache_hits++; - return (0); - } else - mac_vnode_label_cache_misses++; - - if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - } - - error = VOP_REFRESHLABEL(vp, cred, curthread); - switch (error) { - case EOPNOTSUPP: - /* - * If labels are not supported on this vnode, fall back to - * the label in the mount and propagate it to the vnode. - * There should probably be some sort of policy/flag/decision - * about doing this. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - default: + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); return (error); } -} -/* - * Helper function for file systems using the vop_std*_ea() calls. This - * function must be called after EA service is available for the vnode, - * but before it's hooked up to the namespace so that the node persists - * if there's a crash, or before it can be accessed. On successful - * commit of the label to disk (etc), do cache the label. - */ -int -vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) -{ - struct oldmac extmac; - int error; + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); - ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); - if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(tvp, tvp->v_mount); - } else { - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); + if (error == EOPNOTSUPP) + error = 0; /* XXX */ - /* - * Stick the label in the vnode. Then try to write to - * disk. If we fail, return a failure to abort the - * create operation. Really, this failure shouldn't - * happen except in fairly unusual circumstances (out - * of disk, etc). - */ - mac_create_vnode(cred, dvp, tvp); - - error = mac_stdcreatevnode_ea(tvp); - if (error) - return (error); - - /* - * XXX: Eventually this will go away and all policies will - * directly manage their extended attributes. - */ - error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac); - if (error) - return (error); - - error = vn_extattr_set(tvp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); - if (error == 0) - tvp->v_vflag |= VV_CACHEDLABEL; - else { -#if 0 - /* - * In theory, we could have fall-back behavior here. - * It would probably be incorrect. - */ -#endif - return (error); - } - } - - return (0); + return (error); } void mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) { - int error; ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); - error = vn_refreshlabel(vp, old); - if (error) { - printf("mac_execve_transition: vn_refreshlabel returned %d\n", - error); - printf("mac_execve_transition: using old vnode label\n"); - } - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); } int mac_execve_will_transition(struct ucred *old, struct vnode *vp) { - int error, result; - - error = vn_refreshlabel(vp, old); - if (error) - return (error); + int result; result = 0; MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); @@ -2040,10 +1860,6 @@ mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); return (error); } @@ -2058,10 +1874,6 @@ mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); return (error); } @@ -2076,10 +1888,6 @@ mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); return (error); } @@ -2095,10 +1903,6 @@ mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); return (error); } @@ -2115,13 +1919,6 @@ mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2138,10 +1935,6 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); return (error); } @@ -2156,9 +1949,6 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); return (error); @@ -2174,10 +1964,6 @@ mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); return (error); } @@ -2193,10 +1979,6 @@ mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2214,14 +1996,6 @@ mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2238,10 +2012,6 @@ mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); return (error); } @@ -2256,10 +2026,6 @@ mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); return (error); } @@ -2290,10 +2056,6 @@ mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); return (error); } @@ -2308,10 +2070,6 @@ mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); return (error); } @@ -2327,10 +2085,6 @@ mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, &vp->v_label); @@ -2348,10 +2102,6 @@ mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, &vp->v_label); @@ -2368,10 +2118,6 @@ mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); return (error); } @@ -2386,10 +2132,6 @@ mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); return (error); } @@ -2402,10 +2144,6 @@ mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); return (error); @@ -2423,13 +2161,6 @@ mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2447,14 +2178,6 @@ mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - if (vp != NULL) { - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - } MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, vp != NULL ? &vp->v_label : NULL, samedir, cnp); return (error); @@ -2470,10 +2193,6 @@ mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); return (error); } @@ -2489,10 +2208,6 @@ mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); return (error); } @@ -2508,10 +2223,6 @@ mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2527,10 +2238,6 @@ mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); return (error); } @@ -2545,10 +2252,6 @@ mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); return (error); } @@ -2564,10 +2267,6 @@ mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); return (error); } @@ -2583,10 +2282,6 @@ mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, mtime); return (error); @@ -2603,10 +2298,6 @@ mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, &vp->v_label); return (error); @@ -2622,10 +2313,6 @@ mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label); return (error); } @@ -2641,10 +2328,6 @@ mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, &vp->v_label); @@ -3344,7 +3027,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3352,7 +3034,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_ifnet_label(&ifnet->if_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3382,7 +3063,6 @@ mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3444,16 +3124,6 @@ mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, &de->de_label); } -static int -mac_stdcreatevnode_ea(struct vnode *vp) -{ - int error; - - MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); - - return (error); -} - void mac_create_devfs_directory(char *dirname, int dirnamelen, struct devfs_dirent *de) @@ -3463,29 +3133,6 @@ mac_create_devfs_directory(char *dirname, int dirnamelen, &de->de_label); } -/* - * When a new vnode is created, this call will initialize its label. - */ -void -mac_create_vnode(struct ucred *cred, struct vnode *parent, - struct vnode *child) -{ - int error; - - ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); - ASSERT_VOP_LOCKED(child, "mac_create_vnode"); - - error = vn_refreshlabel(parent, cred); - if (error) { - printf("mac_create_vnode: vn_refreshlabel returned %d\n", - error); - printf("mac_create_vnode: using old vnode label\n"); - } - - MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, - &child->v_label); -} - int mac_setsockopt_label_set(struct ucred *cred, struct socket *so, struct mac *mac) @@ -3499,7 +3146,6 @@ mac_setsockopt_label_set(struct ucred *cred, struct socket *so, return (error); buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3554,7 +3200,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3562,7 +3207,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_label(&so->so_label, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3586,7 +3230,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3594,7 +3237,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_peer_label(&so->so_peerlabel, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3616,35 +3258,19 @@ vop_stdsetlabel_ea(struct vop_setlabel_args *ap) { struct vnode *vp = ap->a_vp; struct label *intlabel = ap->a_label; - struct oldmac extmac; int error; ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); - /* - * XXX: Eventually call out to EA check/set calls here. - * Be particularly careful to avoid race conditions, - * consistency problems, and stability problems when - * dealing with multiple EAs. In particular, we require - * the ability to write multiple EAs on the same file in - * a single transaction, which the current EA interface - * does not provide. - */ + if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) + return (EOPNOTSUPP); - error = mac_externalize_vnode_oldmac(intlabel, &extmac); - if (error) - return (error); - - error = vn_extattr_set(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); + error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); if (error) return (error); mac_relabel_vnode(ap->a_cred, vp, intlabel); - vp->v_vflag |= VV_CACHEDLABEL; - return (0); } @@ -3721,7 +3347,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3730,7 +3355,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&tcred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3761,7 +3385,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3769,7 +3392,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&td->td_ucred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3802,7 +3424,6 @@ __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3880,7 +3501,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3888,7 +3508,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ error = fget(td, SCARG(uap, fd), &fp); if (error) @@ -3903,9 +3522,7 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) mac_init_vnode_label(&intlabel); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - error = vn_refreshlabel(vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&vp->v_label, &intlabel); + mac_copy_vnode_label(&vp->v_label, &intlabel); VOP_UNLOCK(vp, 0, td); break; @@ -3974,7 +3591,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3982,7 +3598,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -3991,12 +3606,9 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4034,7 +3646,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -4042,7 +3653,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -4051,12 +3661,9 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4096,7 +3703,6 @@ __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4183,7 +3789,6 @@ __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4240,7 +3845,6 @@ __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); diff --git a/sys/security/mac/mac_net.c b/sys/security/mac/mac_net.c index 78bc485c3863..2ff4162fbfb1 100644 --- a/sys/security/mac/mac_net.c +++ b/sys/security/mac/mac_net.c @@ -115,6 +115,12 @@ SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, */ static int mac_late = 0; +/* + * Warn about EA transactions only the first time they happen. + * Weak coherency, no locking. + */ +static int ea_warn_once = 0; + static int mac_enforce_fs = 1; SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); @@ -145,23 +151,12 @@ SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); -static int mac_label_size = sizeof(struct oldmac); -SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, - &mac_label_size, 0, "Pre-compiled MAC label size"); - static int mac_cache_fslabel_in_vnode = 1; SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); TUNABLE_INT("security.mac.cache_fslabel_in_vnode", &mac_cache_fslabel_in_vnode); -static int mac_vnode_label_cache_hits = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, - &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); -static int mac_vnode_label_cache_misses = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, - &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); - static int mac_mmap_revocation = 1; SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " @@ -214,12 +209,9 @@ SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, #endif static int error_select(int error1, int error2); -static int mac_externalize_vnode_oldmac(struct label *label, - struct oldmac *extmac); static int mac_policy_register(struct mac_policy_conf *mpc); static int mac_policy_unregister(struct mac_policy_conf *mpc); -static int mac_stdcreatevnode_ea(struct vnode *vp); static void mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot); static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, @@ -227,6 +219,10 @@ static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, static void mac_destroy_socket_label(struct label *label); +static int mac_setlabel_vnode_extattr(struct ucred *cred, + struct vnode *vp, struct label *intlabel); + + MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); @@ -623,10 +619,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_externalize_vnode_label = mpe->mpe_function; break; - case MAC_EXTERNALIZE_VNODE_OLDMAC: - mpc->mpc_ops->mpo_externalize_vnode_oldmac = - mpe->mpe_function; - break; case MAC_INTERNALIZE_CRED_LABEL: mpc->mpc_ops->mpo_internalize_cred_label = mpe->mpe_function; @@ -663,14 +655,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_create_devfs_vnode = mpe->mpe_function; break; - case MAC_STDCREATEVNODE_EA: - mpc->mpc_ops->mpo_stdcreatevnode_ea = - mpe->mpe_function; - break; - case MAC_CREATE_VNODE: - mpc->mpc_ops->mpo_create_vnode = - mpe->mpe_function; - break; case MAC_CREATE_MOUNT: mpc->mpc_ops->mpo_create_mount = mpe->mpe_function; @@ -687,20 +671,24 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_update_devfsdirent = mpe->mpe_function; break; - case MAC_UPDATE_PROCFSVNODE: - mpc->mpc_ops->mpo_update_procfsvnode = + case MAC_ASSOCIATE_VNODE_DEVFS: + mpc->mpc_ops->mpo_associate_vnode_devfs = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTATTR: - mpc->mpc_ops->mpo_update_vnode_from_extattr = + case MAC_ASSOCIATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_associate_vnode_extattr = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: - mpc->mpc_ops->mpo_update_vnode_from_externalized = + case MAC_ASSOCIATE_VNODE_SINGLELABEL: + mpc->mpc_ops->mpo_associate_vnode_singlelabel = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_MOUNT: - mpc->mpc_ops->mpo_update_vnode_from_mount = + case MAC_CREATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_create_vnode_extattr = + mpe->mpe_function; + break; + case MAC_SETLABEL_VNODE_EXTATTR: + mpc->mpc_ops->mpo_setlabel_vnode_extattr = mpe->mpe_function; break; case MAC_CREATE_MBUF_FROM_SOCKET: @@ -1379,7 +1367,7 @@ mac_init_socket(struct socket *socket, int flag) return (error); } -static void +void mac_init_vnode_label(struct label *label) { @@ -1536,7 +1524,7 @@ mac_destroy_socket(struct socket *socket) mac_destroy_socket_peer_label(&socket->so_peerlabel); } -static void +void mac_destroy_vnode_label(struct label *label) { @@ -1561,7 +1549,7 @@ mac_copy_pipe_label(struct label *src, struct label *dest) MAC_PERFORM(copy_pipe_label, src, dest); } -static void +void mac_copy_vnode_label(struct label *src, struct label *dest) { @@ -1644,16 +1632,6 @@ mac_externalize_vnode_label(struct label *label, char *elements, return (error); } -static int -mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(externalize_vnode_oldmac, label, extmac); - - return (error); -} - static int mac_internalize_cred_label(struct label *label, char *string) { @@ -1753,276 +1731,118 @@ mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) } void -mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) +mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, + struct vnode *vp) { - MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); + MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, + &de->de_label, vp, &vp->v_label); } -/* - * Support callout for policies that manage their own externalization - * using extended attributes. - */ -static int -mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) +int +mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) { int error; - MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, - &mp->mnt_fslabel); + ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); + + MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, + &vp->v_label); return (error); } -/* - * Given an externalized mac label, internalize it and stamp it on a - * vnode. - */ -static int -mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); - - return (error); -} - -/* - * Call out to individual policies to update the label in a vnode from - * the mountpoint. - */ void -mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) +mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) { - MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, - &mp->mnt_fslabel); - - ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); - if (mac_cache_fslabel_in_vnode) - vp->v_vflag |= VV_CACHEDLABEL; + MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, + &vp->v_label); } -/* - * Implementation of VOP_REFRESHLABEL() that relies on extended attributes - * to store label data. Can be referenced by filesystems supporting - * extended attributes. - */ int -vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) +mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { - struct vnode *vp = ap->a_vp; - struct oldmac extmac; - int buflen, error; + int error; - ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); + ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); + ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); - /* - * Call out to external policies first. Order doesn't really - * matter, as long as failure of one assures failure of all. - */ - error = mac_update_vnode_from_extattr(vp, vp->v_mount); - if (error) - return (error); - - buflen = sizeof(extmac); - error = vn_extattr_get(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, - (char *)&extmac, curthread); - switch (error) { - case 0: - /* Got it */ - break; - - case ENOATTR: - /* - * Use the label from the mount point. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - - case EOPNOTSUPP: - default: - /* Fail horribly. */ - return (error); - } - - if (buflen != sizeof(extmac)) - error = EPERM; /* Fail very closed. */ - if (error == 0) - error = mac_update_vnode_from_externalized(vp, &extmac); - if (error == 0) - vp->v_vflag |= VV_CACHEDLABEL; - else { - struct vattr va; - - printf("Corrupted label on %s", - vp->v_mount->mnt_stat.f_mntonname); - if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) - printf(" inum %ld", va.va_fileid); -#ifdef MAC_DEBUG - if (mac_debug_label_fallback) { - printf(", falling back.\n"); - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - } else { -#endif - printf(".\n"); - error = EPERM; -#ifdef MAC_DEBUG + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; } -#endif + } else if (error) + return (error); + + MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, + dvp, &dvp->v_label, vp, &vp->v_label, cnp); + + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); + return (error); } + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); + + if (error == EOPNOTSUPP) + error = 0; /* XXX */ + return (error); } -/* - * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle - * the labeling activity outselves. Filesystems should be careful not - * to change their minds regarding whether they support vop_refreshlabel() - * for a vnode or not. Don't cache the vnode here, allow the file - * system code to determine if it's safe to cache. If we update from - * the mount, don't cache since a change to the mount label should affect - * all vnodes. - */ static int -vn_refreshlabel(struct vnode *vp, struct ucred *cred) +mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *intlabel) { int error; - ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); + ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); - if (vp->v_mount == NULL) { -/* - Eventually, we probably want to special-case refreshing - of deadfs vnodes, and if there's a lock-free race somewhere, - that case might be handled here. + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; + } + } else if (error) + return (error); - mac_update_vnode_deadfs(vp); - return (0); - */ - /* printf("vn_refreshlabel: null v_mount\n"); */ - if (vp->v_type != VNON) - printf( - "vn_refreshlabel: null v_mount with non-VNON\n"); - return (EBADF); - } + MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); - if (vp->v_vflag & VV_CACHEDLABEL) { - mac_vnode_label_cache_hits++; - return (0); - } else - mac_vnode_label_cache_misses++; - - if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - } - - error = VOP_REFRESHLABEL(vp, cred, curthread); - switch (error) { - case EOPNOTSUPP: - /* - * If labels are not supported on this vnode, fall back to - * the label in the mount and propagate it to the vnode. - * There should probably be some sort of policy/flag/decision - * about doing this. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - default: + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); return (error); } -} -/* - * Helper function for file systems using the vop_std*_ea() calls. This - * function must be called after EA service is available for the vnode, - * but before it's hooked up to the namespace so that the node persists - * if there's a crash, or before it can be accessed. On successful - * commit of the label to disk (etc), do cache the label. - */ -int -vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) -{ - struct oldmac extmac; - int error; + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); - ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); - if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(tvp, tvp->v_mount); - } else { - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); + if (error == EOPNOTSUPP) + error = 0; /* XXX */ - /* - * Stick the label in the vnode. Then try to write to - * disk. If we fail, return a failure to abort the - * create operation. Really, this failure shouldn't - * happen except in fairly unusual circumstances (out - * of disk, etc). - */ - mac_create_vnode(cred, dvp, tvp); - - error = mac_stdcreatevnode_ea(tvp); - if (error) - return (error); - - /* - * XXX: Eventually this will go away and all policies will - * directly manage their extended attributes. - */ - error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac); - if (error) - return (error); - - error = vn_extattr_set(tvp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); - if (error == 0) - tvp->v_vflag |= VV_CACHEDLABEL; - else { -#if 0 - /* - * In theory, we could have fall-back behavior here. - * It would probably be incorrect. - */ -#endif - return (error); - } - } - - return (0); + return (error); } void mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) { - int error; ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); - error = vn_refreshlabel(vp, old); - if (error) { - printf("mac_execve_transition: vn_refreshlabel returned %d\n", - error); - printf("mac_execve_transition: using old vnode label\n"); - } - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); } int mac_execve_will_transition(struct ucred *old, struct vnode *vp) { - int error, result; - - error = vn_refreshlabel(vp, old); - if (error) - return (error); + int result; result = 0; MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); @@ -2040,10 +1860,6 @@ mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); return (error); } @@ -2058,10 +1874,6 @@ mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); return (error); } @@ -2076,10 +1888,6 @@ mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); return (error); } @@ -2095,10 +1903,6 @@ mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); return (error); } @@ -2115,13 +1919,6 @@ mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2138,10 +1935,6 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); return (error); } @@ -2156,9 +1949,6 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); return (error); @@ -2174,10 +1964,6 @@ mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); return (error); } @@ -2193,10 +1979,6 @@ mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2214,14 +1996,6 @@ mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2238,10 +2012,6 @@ mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); return (error); } @@ -2256,10 +2026,6 @@ mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); return (error); } @@ -2290,10 +2056,6 @@ mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); return (error); } @@ -2308,10 +2070,6 @@ mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); return (error); } @@ -2327,10 +2085,6 @@ mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, &vp->v_label); @@ -2348,10 +2102,6 @@ mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, &vp->v_label); @@ -2368,10 +2118,6 @@ mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); return (error); } @@ -2386,10 +2132,6 @@ mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); return (error); } @@ -2402,10 +2144,6 @@ mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); return (error); @@ -2423,13 +2161,6 @@ mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2447,14 +2178,6 @@ mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - if (vp != NULL) { - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - } MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, vp != NULL ? &vp->v_label : NULL, samedir, cnp); return (error); @@ -2470,10 +2193,6 @@ mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); return (error); } @@ -2489,10 +2208,6 @@ mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); return (error); } @@ -2508,10 +2223,6 @@ mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2527,10 +2238,6 @@ mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); return (error); } @@ -2545,10 +2252,6 @@ mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); return (error); } @@ -2564,10 +2267,6 @@ mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); return (error); } @@ -2583,10 +2282,6 @@ mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, mtime); return (error); @@ -2603,10 +2298,6 @@ mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, &vp->v_label); return (error); @@ -2622,10 +2313,6 @@ mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label); return (error); } @@ -2641,10 +2328,6 @@ mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, &vp->v_label); @@ -3344,7 +3027,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3352,7 +3034,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_ifnet_label(&ifnet->if_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3382,7 +3063,6 @@ mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3444,16 +3124,6 @@ mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, &de->de_label); } -static int -mac_stdcreatevnode_ea(struct vnode *vp) -{ - int error; - - MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); - - return (error); -} - void mac_create_devfs_directory(char *dirname, int dirnamelen, struct devfs_dirent *de) @@ -3463,29 +3133,6 @@ mac_create_devfs_directory(char *dirname, int dirnamelen, &de->de_label); } -/* - * When a new vnode is created, this call will initialize its label. - */ -void -mac_create_vnode(struct ucred *cred, struct vnode *parent, - struct vnode *child) -{ - int error; - - ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); - ASSERT_VOP_LOCKED(child, "mac_create_vnode"); - - error = vn_refreshlabel(parent, cred); - if (error) { - printf("mac_create_vnode: vn_refreshlabel returned %d\n", - error); - printf("mac_create_vnode: using old vnode label\n"); - } - - MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, - &child->v_label); -} - int mac_setsockopt_label_set(struct ucred *cred, struct socket *so, struct mac *mac) @@ -3499,7 +3146,6 @@ mac_setsockopt_label_set(struct ucred *cred, struct socket *so, return (error); buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3554,7 +3200,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3562,7 +3207,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_label(&so->so_label, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3586,7 +3230,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3594,7 +3237,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_peer_label(&so->so_peerlabel, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3616,35 +3258,19 @@ vop_stdsetlabel_ea(struct vop_setlabel_args *ap) { struct vnode *vp = ap->a_vp; struct label *intlabel = ap->a_label; - struct oldmac extmac; int error; ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); - /* - * XXX: Eventually call out to EA check/set calls here. - * Be particularly careful to avoid race conditions, - * consistency problems, and stability problems when - * dealing with multiple EAs. In particular, we require - * the ability to write multiple EAs on the same file in - * a single transaction, which the current EA interface - * does not provide. - */ + if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) + return (EOPNOTSUPP); - error = mac_externalize_vnode_oldmac(intlabel, &extmac); - if (error) - return (error); - - error = vn_extattr_set(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); + error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); if (error) return (error); mac_relabel_vnode(ap->a_cred, vp, intlabel); - vp->v_vflag |= VV_CACHEDLABEL; - return (0); } @@ -3721,7 +3347,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3730,7 +3355,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&tcred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3761,7 +3385,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3769,7 +3392,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&td->td_ucred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3802,7 +3424,6 @@ __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3880,7 +3501,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3888,7 +3508,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ error = fget(td, SCARG(uap, fd), &fp); if (error) @@ -3903,9 +3522,7 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) mac_init_vnode_label(&intlabel); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - error = vn_refreshlabel(vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&vp->v_label, &intlabel); + mac_copy_vnode_label(&vp->v_label, &intlabel); VOP_UNLOCK(vp, 0, td); break; @@ -3974,7 +3591,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3982,7 +3598,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -3991,12 +3606,9 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4034,7 +3646,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -4042,7 +3653,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -4051,12 +3661,9 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4096,7 +3703,6 @@ __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4183,7 +3789,6 @@ __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4240,7 +3845,6 @@ __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); diff --git a/sys/security/mac/mac_pipe.c b/sys/security/mac/mac_pipe.c index 78bc485c3863..2ff4162fbfb1 100644 --- a/sys/security/mac/mac_pipe.c +++ b/sys/security/mac/mac_pipe.c @@ -115,6 +115,12 @@ SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, */ static int mac_late = 0; +/* + * Warn about EA transactions only the first time they happen. + * Weak coherency, no locking. + */ +static int ea_warn_once = 0; + static int mac_enforce_fs = 1; SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); @@ -145,23 +151,12 @@ SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); -static int mac_label_size = sizeof(struct oldmac); -SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, - &mac_label_size, 0, "Pre-compiled MAC label size"); - static int mac_cache_fslabel_in_vnode = 1; SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); TUNABLE_INT("security.mac.cache_fslabel_in_vnode", &mac_cache_fslabel_in_vnode); -static int mac_vnode_label_cache_hits = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, - &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); -static int mac_vnode_label_cache_misses = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, - &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); - static int mac_mmap_revocation = 1; SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " @@ -214,12 +209,9 @@ SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, #endif static int error_select(int error1, int error2); -static int mac_externalize_vnode_oldmac(struct label *label, - struct oldmac *extmac); static int mac_policy_register(struct mac_policy_conf *mpc); static int mac_policy_unregister(struct mac_policy_conf *mpc); -static int mac_stdcreatevnode_ea(struct vnode *vp); static void mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot); static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, @@ -227,6 +219,10 @@ static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, static void mac_destroy_socket_label(struct label *label); +static int mac_setlabel_vnode_extattr(struct ucred *cred, + struct vnode *vp, struct label *intlabel); + + MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); @@ -623,10 +619,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_externalize_vnode_label = mpe->mpe_function; break; - case MAC_EXTERNALIZE_VNODE_OLDMAC: - mpc->mpc_ops->mpo_externalize_vnode_oldmac = - mpe->mpe_function; - break; case MAC_INTERNALIZE_CRED_LABEL: mpc->mpc_ops->mpo_internalize_cred_label = mpe->mpe_function; @@ -663,14 +655,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_create_devfs_vnode = mpe->mpe_function; break; - case MAC_STDCREATEVNODE_EA: - mpc->mpc_ops->mpo_stdcreatevnode_ea = - mpe->mpe_function; - break; - case MAC_CREATE_VNODE: - mpc->mpc_ops->mpo_create_vnode = - mpe->mpe_function; - break; case MAC_CREATE_MOUNT: mpc->mpc_ops->mpo_create_mount = mpe->mpe_function; @@ -687,20 +671,24 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_update_devfsdirent = mpe->mpe_function; break; - case MAC_UPDATE_PROCFSVNODE: - mpc->mpc_ops->mpo_update_procfsvnode = + case MAC_ASSOCIATE_VNODE_DEVFS: + mpc->mpc_ops->mpo_associate_vnode_devfs = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTATTR: - mpc->mpc_ops->mpo_update_vnode_from_extattr = + case MAC_ASSOCIATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_associate_vnode_extattr = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: - mpc->mpc_ops->mpo_update_vnode_from_externalized = + case MAC_ASSOCIATE_VNODE_SINGLELABEL: + mpc->mpc_ops->mpo_associate_vnode_singlelabel = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_MOUNT: - mpc->mpc_ops->mpo_update_vnode_from_mount = + case MAC_CREATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_create_vnode_extattr = + mpe->mpe_function; + break; + case MAC_SETLABEL_VNODE_EXTATTR: + mpc->mpc_ops->mpo_setlabel_vnode_extattr = mpe->mpe_function; break; case MAC_CREATE_MBUF_FROM_SOCKET: @@ -1379,7 +1367,7 @@ mac_init_socket(struct socket *socket, int flag) return (error); } -static void +void mac_init_vnode_label(struct label *label) { @@ -1536,7 +1524,7 @@ mac_destroy_socket(struct socket *socket) mac_destroy_socket_peer_label(&socket->so_peerlabel); } -static void +void mac_destroy_vnode_label(struct label *label) { @@ -1561,7 +1549,7 @@ mac_copy_pipe_label(struct label *src, struct label *dest) MAC_PERFORM(copy_pipe_label, src, dest); } -static void +void mac_copy_vnode_label(struct label *src, struct label *dest) { @@ -1644,16 +1632,6 @@ mac_externalize_vnode_label(struct label *label, char *elements, return (error); } -static int -mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(externalize_vnode_oldmac, label, extmac); - - return (error); -} - static int mac_internalize_cred_label(struct label *label, char *string) { @@ -1753,276 +1731,118 @@ mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) } void -mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) +mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, + struct vnode *vp) { - MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); + MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, + &de->de_label, vp, &vp->v_label); } -/* - * Support callout for policies that manage their own externalization - * using extended attributes. - */ -static int -mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) +int +mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) { int error; - MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, - &mp->mnt_fslabel); + ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); + + MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, + &vp->v_label); return (error); } -/* - * Given an externalized mac label, internalize it and stamp it on a - * vnode. - */ -static int -mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); - - return (error); -} - -/* - * Call out to individual policies to update the label in a vnode from - * the mountpoint. - */ void -mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) +mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) { - MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, - &mp->mnt_fslabel); - - ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); - if (mac_cache_fslabel_in_vnode) - vp->v_vflag |= VV_CACHEDLABEL; + MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, + &vp->v_label); } -/* - * Implementation of VOP_REFRESHLABEL() that relies on extended attributes - * to store label data. Can be referenced by filesystems supporting - * extended attributes. - */ int -vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) +mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { - struct vnode *vp = ap->a_vp; - struct oldmac extmac; - int buflen, error; + int error; - ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); + ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); + ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); - /* - * Call out to external policies first. Order doesn't really - * matter, as long as failure of one assures failure of all. - */ - error = mac_update_vnode_from_extattr(vp, vp->v_mount); - if (error) - return (error); - - buflen = sizeof(extmac); - error = vn_extattr_get(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, - (char *)&extmac, curthread); - switch (error) { - case 0: - /* Got it */ - break; - - case ENOATTR: - /* - * Use the label from the mount point. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - - case EOPNOTSUPP: - default: - /* Fail horribly. */ - return (error); - } - - if (buflen != sizeof(extmac)) - error = EPERM; /* Fail very closed. */ - if (error == 0) - error = mac_update_vnode_from_externalized(vp, &extmac); - if (error == 0) - vp->v_vflag |= VV_CACHEDLABEL; - else { - struct vattr va; - - printf("Corrupted label on %s", - vp->v_mount->mnt_stat.f_mntonname); - if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) - printf(" inum %ld", va.va_fileid); -#ifdef MAC_DEBUG - if (mac_debug_label_fallback) { - printf(", falling back.\n"); - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - } else { -#endif - printf(".\n"); - error = EPERM; -#ifdef MAC_DEBUG + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; } -#endif + } else if (error) + return (error); + + MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, + dvp, &dvp->v_label, vp, &vp->v_label, cnp); + + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); + return (error); } + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); + + if (error == EOPNOTSUPP) + error = 0; /* XXX */ + return (error); } -/* - * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle - * the labeling activity outselves. Filesystems should be careful not - * to change their minds regarding whether they support vop_refreshlabel() - * for a vnode or not. Don't cache the vnode here, allow the file - * system code to determine if it's safe to cache. If we update from - * the mount, don't cache since a change to the mount label should affect - * all vnodes. - */ static int -vn_refreshlabel(struct vnode *vp, struct ucred *cred) +mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *intlabel) { int error; - ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); + ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); - if (vp->v_mount == NULL) { -/* - Eventually, we probably want to special-case refreshing - of deadfs vnodes, and if there's a lock-free race somewhere, - that case might be handled here. + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; + } + } else if (error) + return (error); - mac_update_vnode_deadfs(vp); - return (0); - */ - /* printf("vn_refreshlabel: null v_mount\n"); */ - if (vp->v_type != VNON) - printf( - "vn_refreshlabel: null v_mount with non-VNON\n"); - return (EBADF); - } + MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); - if (vp->v_vflag & VV_CACHEDLABEL) { - mac_vnode_label_cache_hits++; - return (0); - } else - mac_vnode_label_cache_misses++; - - if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - } - - error = VOP_REFRESHLABEL(vp, cred, curthread); - switch (error) { - case EOPNOTSUPP: - /* - * If labels are not supported on this vnode, fall back to - * the label in the mount and propagate it to the vnode. - * There should probably be some sort of policy/flag/decision - * about doing this. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - default: + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); return (error); } -} -/* - * Helper function for file systems using the vop_std*_ea() calls. This - * function must be called after EA service is available for the vnode, - * but before it's hooked up to the namespace so that the node persists - * if there's a crash, or before it can be accessed. On successful - * commit of the label to disk (etc), do cache the label. - */ -int -vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) -{ - struct oldmac extmac; - int error; + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); - ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); - if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(tvp, tvp->v_mount); - } else { - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); + if (error == EOPNOTSUPP) + error = 0; /* XXX */ - /* - * Stick the label in the vnode. Then try to write to - * disk. If we fail, return a failure to abort the - * create operation. Really, this failure shouldn't - * happen except in fairly unusual circumstances (out - * of disk, etc). - */ - mac_create_vnode(cred, dvp, tvp); - - error = mac_stdcreatevnode_ea(tvp); - if (error) - return (error); - - /* - * XXX: Eventually this will go away and all policies will - * directly manage their extended attributes. - */ - error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac); - if (error) - return (error); - - error = vn_extattr_set(tvp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); - if (error == 0) - tvp->v_vflag |= VV_CACHEDLABEL; - else { -#if 0 - /* - * In theory, we could have fall-back behavior here. - * It would probably be incorrect. - */ -#endif - return (error); - } - } - - return (0); + return (error); } void mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) { - int error; ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); - error = vn_refreshlabel(vp, old); - if (error) { - printf("mac_execve_transition: vn_refreshlabel returned %d\n", - error); - printf("mac_execve_transition: using old vnode label\n"); - } - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); } int mac_execve_will_transition(struct ucred *old, struct vnode *vp) { - int error, result; - - error = vn_refreshlabel(vp, old); - if (error) - return (error); + int result; result = 0; MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); @@ -2040,10 +1860,6 @@ mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); return (error); } @@ -2058,10 +1874,6 @@ mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); return (error); } @@ -2076,10 +1888,6 @@ mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); return (error); } @@ -2095,10 +1903,6 @@ mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); return (error); } @@ -2115,13 +1919,6 @@ mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2138,10 +1935,6 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); return (error); } @@ -2156,9 +1949,6 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); return (error); @@ -2174,10 +1964,6 @@ mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); return (error); } @@ -2193,10 +1979,6 @@ mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2214,14 +1996,6 @@ mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2238,10 +2012,6 @@ mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); return (error); } @@ -2256,10 +2026,6 @@ mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); return (error); } @@ -2290,10 +2056,6 @@ mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); return (error); } @@ -2308,10 +2070,6 @@ mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); return (error); } @@ -2327,10 +2085,6 @@ mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, &vp->v_label); @@ -2348,10 +2102,6 @@ mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, &vp->v_label); @@ -2368,10 +2118,6 @@ mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); return (error); } @@ -2386,10 +2132,6 @@ mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); return (error); } @@ -2402,10 +2144,6 @@ mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); return (error); @@ -2423,13 +2161,6 @@ mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2447,14 +2178,6 @@ mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - if (vp != NULL) { - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - } MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, vp != NULL ? &vp->v_label : NULL, samedir, cnp); return (error); @@ -2470,10 +2193,6 @@ mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); return (error); } @@ -2489,10 +2208,6 @@ mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); return (error); } @@ -2508,10 +2223,6 @@ mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2527,10 +2238,6 @@ mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); return (error); } @@ -2545,10 +2252,6 @@ mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); return (error); } @@ -2564,10 +2267,6 @@ mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); return (error); } @@ -2583,10 +2282,6 @@ mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, mtime); return (error); @@ -2603,10 +2298,6 @@ mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, &vp->v_label); return (error); @@ -2622,10 +2313,6 @@ mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label); return (error); } @@ -2641,10 +2328,6 @@ mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, &vp->v_label); @@ -3344,7 +3027,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3352,7 +3034,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_ifnet_label(&ifnet->if_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3382,7 +3063,6 @@ mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3444,16 +3124,6 @@ mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, &de->de_label); } -static int -mac_stdcreatevnode_ea(struct vnode *vp) -{ - int error; - - MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); - - return (error); -} - void mac_create_devfs_directory(char *dirname, int dirnamelen, struct devfs_dirent *de) @@ -3463,29 +3133,6 @@ mac_create_devfs_directory(char *dirname, int dirnamelen, &de->de_label); } -/* - * When a new vnode is created, this call will initialize its label. - */ -void -mac_create_vnode(struct ucred *cred, struct vnode *parent, - struct vnode *child) -{ - int error; - - ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); - ASSERT_VOP_LOCKED(child, "mac_create_vnode"); - - error = vn_refreshlabel(parent, cred); - if (error) { - printf("mac_create_vnode: vn_refreshlabel returned %d\n", - error); - printf("mac_create_vnode: using old vnode label\n"); - } - - MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, - &child->v_label); -} - int mac_setsockopt_label_set(struct ucred *cred, struct socket *so, struct mac *mac) @@ -3499,7 +3146,6 @@ mac_setsockopt_label_set(struct ucred *cred, struct socket *so, return (error); buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3554,7 +3200,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3562,7 +3207,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_label(&so->so_label, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3586,7 +3230,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3594,7 +3237,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_peer_label(&so->so_peerlabel, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3616,35 +3258,19 @@ vop_stdsetlabel_ea(struct vop_setlabel_args *ap) { struct vnode *vp = ap->a_vp; struct label *intlabel = ap->a_label; - struct oldmac extmac; int error; ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); - /* - * XXX: Eventually call out to EA check/set calls here. - * Be particularly careful to avoid race conditions, - * consistency problems, and stability problems when - * dealing with multiple EAs. In particular, we require - * the ability to write multiple EAs on the same file in - * a single transaction, which the current EA interface - * does not provide. - */ + if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) + return (EOPNOTSUPP); - error = mac_externalize_vnode_oldmac(intlabel, &extmac); - if (error) - return (error); - - error = vn_extattr_set(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); + error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); if (error) return (error); mac_relabel_vnode(ap->a_cred, vp, intlabel); - vp->v_vflag |= VV_CACHEDLABEL; - return (0); } @@ -3721,7 +3347,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3730,7 +3355,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&tcred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3761,7 +3385,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3769,7 +3392,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&td->td_ucred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3802,7 +3424,6 @@ __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3880,7 +3501,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3888,7 +3508,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ error = fget(td, SCARG(uap, fd), &fp); if (error) @@ -3903,9 +3522,7 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) mac_init_vnode_label(&intlabel); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - error = vn_refreshlabel(vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&vp->v_label, &intlabel); + mac_copy_vnode_label(&vp->v_label, &intlabel); VOP_UNLOCK(vp, 0, td); break; @@ -3974,7 +3591,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3982,7 +3598,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -3991,12 +3606,9 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4034,7 +3646,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -4042,7 +3653,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -4051,12 +3661,9 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4096,7 +3703,6 @@ __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4183,7 +3789,6 @@ __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4240,7 +3845,6 @@ __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h index aabc95e3e745..46c4c1bc558f 100644 --- a/sys/security/mac/mac_policy.h +++ b/sys/security/mac/mac_policy.h @@ -118,8 +118,6 @@ struct mac_policy_ops { int (*mpo_externalize_vnode_label)(struct label *label, char *element_name, char *buffer, size_t buflen, size_t *len, int *claimed); - int (*mpo_externalize_vnode_oldmac)(struct label *label, - struct oldmac *extmac); int (*mpo_internalize_cred_label)(struct label *label, char *element_name, char *element_data, int *claimed); int (*mpo_internalize_ifnet_label)(struct label *label, @@ -135,6 +133,16 @@ struct mac_policy_ops { * Labeling event operations: file system objects, and things that * look a lot like file system objects. */ + void (*mpo_associate_vnode_devfs)(struct mount *mp, + struct label *fslabel, struct devfs_dirent *de, + struct label *delabel, struct vnode *vp, + struct label *vlabel); + int (*mpo_associate_vnode_extattr)(struct mount *mp, + struct label *fslabel, struct vnode *vp, + struct label *vlabel); + void (*mpo_associate_vnode_singlelabel)(struct mount *mp, + struct label *fslabel, struct vnode *vp, + struct label *vlabel); void (*mpo_create_devfs_device)(dev_t dev, struct devfs_dirent *de, struct label *label); void (*mpo_create_devfs_directory)(char *dirname, int dirnamelen, @@ -145,30 +153,23 @@ struct mac_policy_ops { void (*mpo_create_devfs_vnode)(struct devfs_dirent *de, struct label *direntlabel, struct vnode *vp, struct label *vnodelabel); - void (*mpo_create_vnode)(struct ucred *cred, struct vnode *parent, - struct label *parentlabel, struct vnode *child, - struct label *childlabel); + int (*mpo_create_vnode_extattr)(struct ucred *cred, + struct mount *mp, struct label *fslabel, + struct vnode *dvp, struct label *dlabel, + struct vnode *vp, struct label *vlabel, + struct componentname *cnp); void (*mpo_create_mount)(struct ucred *cred, struct mount *mp, struct label *mntlabel, struct label *fslabel); void (*mpo_create_root_mount)(struct ucred *cred, struct mount *mp, struct label *mountlabel, struct label *fslabel); void (*mpo_relabel_vnode)(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *label); - int (*mpo_stdcreatevnode_ea)(struct vnode *vp, - struct label *vnodelabel); + int (*mpo_setlabel_vnode_extattr)(struct ucred *cred, + struct vnode *vp, struct label *vlabel, + struct label *intlabel); void (*mpo_update_devfsdirent)(struct devfs_dirent *devfs_dirent, struct label *direntlabel, struct vnode *vp, struct label *vnodelabel); - void (*mpo_update_procfsvnode)(struct vnode *vp, - struct label *vnodelabel, struct ucred *cred); - int (*mpo_update_vnode_from_extattr)(struct vnode *vp, - struct label *vnodelabel, struct mount *mp, - struct label *fslabel); - int (*mpo_update_vnode_from_externalized)(struct vnode *vp, - struct label *vnodelabel, struct oldmac *extmac); - void (*mpo_update_vnode_from_mount)(struct vnode *vp, - struct label *vnodelabel, struct mount *mp, - struct label *fslabel); /* * Labeling event operations: IPC objects. @@ -431,7 +432,6 @@ enum mac_op_constant { MAC_EXTERNALIZE_SOCKET_LABEL, MAC_EXTERNALIZE_SOCKET_PEER_LABEL, MAC_EXTERNALIZE_VNODE_LABEL, - MAC_EXTERNALIZE_VNODE_OLDMAC, MAC_INTERNALIZE_CRED_LABEL, MAC_INTERNALIZE_IFNET_LABEL, MAC_INTERNALIZE_PIPE_LABEL, @@ -441,16 +441,15 @@ enum mac_op_constant { MAC_CREATE_DEVFS_DIRECTORY, MAC_CREATE_DEVFS_SYMLINK, MAC_CREATE_DEVFS_VNODE, - MAC_CREATE_VNODE, MAC_CREATE_MOUNT, MAC_CREATE_ROOT_MOUNT, MAC_RELABEL_VNODE, - MAC_STDCREATEVNODE_EA, MAC_UPDATE_DEVFSDIRENT, - MAC_UPDATE_PROCFSVNODE, - MAC_UPDATE_VNODE_FROM_EXTATTR, - MAC_UPDATE_VNODE_FROM_EXTERNALIZED, - MAC_UPDATE_VNODE_FROM_MOUNT, + MAC_ASSOCIATE_VNODE_DEVFS, + MAC_ASSOCIATE_VNODE_EXTATTR, + MAC_ASSOCIATE_VNODE_SINGLELABEL, + MAC_CREATE_VNODE_EXTATTR, + MAC_SETLABEL_VNODE_EXTATTR, MAC_CREATE_MBUF_FROM_SOCKET, MAC_CREATE_PIPE, MAC_CREATE_SOCKET, diff --git a/sys/security/mac/mac_process.c b/sys/security/mac/mac_process.c index 78bc485c3863..2ff4162fbfb1 100644 --- a/sys/security/mac/mac_process.c +++ b/sys/security/mac/mac_process.c @@ -115,6 +115,12 @@ SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, */ static int mac_late = 0; +/* + * Warn about EA transactions only the first time they happen. + * Weak coherency, no locking. + */ +static int ea_warn_once = 0; + static int mac_enforce_fs = 1; SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); @@ -145,23 +151,12 @@ SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); -static int mac_label_size = sizeof(struct oldmac); -SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, - &mac_label_size, 0, "Pre-compiled MAC label size"); - static int mac_cache_fslabel_in_vnode = 1; SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); TUNABLE_INT("security.mac.cache_fslabel_in_vnode", &mac_cache_fslabel_in_vnode); -static int mac_vnode_label_cache_hits = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, - &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); -static int mac_vnode_label_cache_misses = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, - &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); - static int mac_mmap_revocation = 1; SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " @@ -214,12 +209,9 @@ SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, #endif static int error_select(int error1, int error2); -static int mac_externalize_vnode_oldmac(struct label *label, - struct oldmac *extmac); static int mac_policy_register(struct mac_policy_conf *mpc); static int mac_policy_unregister(struct mac_policy_conf *mpc); -static int mac_stdcreatevnode_ea(struct vnode *vp); static void mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot); static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, @@ -227,6 +219,10 @@ static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, static void mac_destroy_socket_label(struct label *label); +static int mac_setlabel_vnode_extattr(struct ucred *cred, + struct vnode *vp, struct label *intlabel); + + MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); @@ -623,10 +619,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_externalize_vnode_label = mpe->mpe_function; break; - case MAC_EXTERNALIZE_VNODE_OLDMAC: - mpc->mpc_ops->mpo_externalize_vnode_oldmac = - mpe->mpe_function; - break; case MAC_INTERNALIZE_CRED_LABEL: mpc->mpc_ops->mpo_internalize_cred_label = mpe->mpe_function; @@ -663,14 +655,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_create_devfs_vnode = mpe->mpe_function; break; - case MAC_STDCREATEVNODE_EA: - mpc->mpc_ops->mpo_stdcreatevnode_ea = - mpe->mpe_function; - break; - case MAC_CREATE_VNODE: - mpc->mpc_ops->mpo_create_vnode = - mpe->mpe_function; - break; case MAC_CREATE_MOUNT: mpc->mpc_ops->mpo_create_mount = mpe->mpe_function; @@ -687,20 +671,24 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_update_devfsdirent = mpe->mpe_function; break; - case MAC_UPDATE_PROCFSVNODE: - mpc->mpc_ops->mpo_update_procfsvnode = + case MAC_ASSOCIATE_VNODE_DEVFS: + mpc->mpc_ops->mpo_associate_vnode_devfs = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTATTR: - mpc->mpc_ops->mpo_update_vnode_from_extattr = + case MAC_ASSOCIATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_associate_vnode_extattr = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: - mpc->mpc_ops->mpo_update_vnode_from_externalized = + case MAC_ASSOCIATE_VNODE_SINGLELABEL: + mpc->mpc_ops->mpo_associate_vnode_singlelabel = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_MOUNT: - mpc->mpc_ops->mpo_update_vnode_from_mount = + case MAC_CREATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_create_vnode_extattr = + mpe->mpe_function; + break; + case MAC_SETLABEL_VNODE_EXTATTR: + mpc->mpc_ops->mpo_setlabel_vnode_extattr = mpe->mpe_function; break; case MAC_CREATE_MBUF_FROM_SOCKET: @@ -1379,7 +1367,7 @@ mac_init_socket(struct socket *socket, int flag) return (error); } -static void +void mac_init_vnode_label(struct label *label) { @@ -1536,7 +1524,7 @@ mac_destroy_socket(struct socket *socket) mac_destroy_socket_peer_label(&socket->so_peerlabel); } -static void +void mac_destroy_vnode_label(struct label *label) { @@ -1561,7 +1549,7 @@ mac_copy_pipe_label(struct label *src, struct label *dest) MAC_PERFORM(copy_pipe_label, src, dest); } -static void +void mac_copy_vnode_label(struct label *src, struct label *dest) { @@ -1644,16 +1632,6 @@ mac_externalize_vnode_label(struct label *label, char *elements, return (error); } -static int -mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(externalize_vnode_oldmac, label, extmac); - - return (error); -} - static int mac_internalize_cred_label(struct label *label, char *string) { @@ -1753,276 +1731,118 @@ mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) } void -mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) +mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, + struct vnode *vp) { - MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); + MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, + &de->de_label, vp, &vp->v_label); } -/* - * Support callout for policies that manage their own externalization - * using extended attributes. - */ -static int -mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) +int +mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) { int error; - MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, - &mp->mnt_fslabel); + ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); + + MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, + &vp->v_label); return (error); } -/* - * Given an externalized mac label, internalize it and stamp it on a - * vnode. - */ -static int -mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); - - return (error); -} - -/* - * Call out to individual policies to update the label in a vnode from - * the mountpoint. - */ void -mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) +mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) { - MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, - &mp->mnt_fslabel); - - ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); - if (mac_cache_fslabel_in_vnode) - vp->v_vflag |= VV_CACHEDLABEL; + MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, + &vp->v_label); } -/* - * Implementation of VOP_REFRESHLABEL() that relies on extended attributes - * to store label data. Can be referenced by filesystems supporting - * extended attributes. - */ int -vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) +mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { - struct vnode *vp = ap->a_vp; - struct oldmac extmac; - int buflen, error; + int error; - ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); + ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); + ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); - /* - * Call out to external policies first. Order doesn't really - * matter, as long as failure of one assures failure of all. - */ - error = mac_update_vnode_from_extattr(vp, vp->v_mount); - if (error) - return (error); - - buflen = sizeof(extmac); - error = vn_extattr_get(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, - (char *)&extmac, curthread); - switch (error) { - case 0: - /* Got it */ - break; - - case ENOATTR: - /* - * Use the label from the mount point. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - - case EOPNOTSUPP: - default: - /* Fail horribly. */ - return (error); - } - - if (buflen != sizeof(extmac)) - error = EPERM; /* Fail very closed. */ - if (error == 0) - error = mac_update_vnode_from_externalized(vp, &extmac); - if (error == 0) - vp->v_vflag |= VV_CACHEDLABEL; - else { - struct vattr va; - - printf("Corrupted label on %s", - vp->v_mount->mnt_stat.f_mntonname); - if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) - printf(" inum %ld", va.va_fileid); -#ifdef MAC_DEBUG - if (mac_debug_label_fallback) { - printf(", falling back.\n"); - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - } else { -#endif - printf(".\n"); - error = EPERM; -#ifdef MAC_DEBUG + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; } -#endif + } else if (error) + return (error); + + MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, + dvp, &dvp->v_label, vp, &vp->v_label, cnp); + + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); + return (error); } + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); + + if (error == EOPNOTSUPP) + error = 0; /* XXX */ + return (error); } -/* - * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle - * the labeling activity outselves. Filesystems should be careful not - * to change their minds regarding whether they support vop_refreshlabel() - * for a vnode or not. Don't cache the vnode here, allow the file - * system code to determine if it's safe to cache. If we update from - * the mount, don't cache since a change to the mount label should affect - * all vnodes. - */ static int -vn_refreshlabel(struct vnode *vp, struct ucred *cred) +mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *intlabel) { int error; - ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); + ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); - if (vp->v_mount == NULL) { -/* - Eventually, we probably want to special-case refreshing - of deadfs vnodes, and if there's a lock-free race somewhere, - that case might be handled here. + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; + } + } else if (error) + return (error); - mac_update_vnode_deadfs(vp); - return (0); - */ - /* printf("vn_refreshlabel: null v_mount\n"); */ - if (vp->v_type != VNON) - printf( - "vn_refreshlabel: null v_mount with non-VNON\n"); - return (EBADF); - } + MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); - if (vp->v_vflag & VV_CACHEDLABEL) { - mac_vnode_label_cache_hits++; - return (0); - } else - mac_vnode_label_cache_misses++; - - if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - } - - error = VOP_REFRESHLABEL(vp, cred, curthread); - switch (error) { - case EOPNOTSUPP: - /* - * If labels are not supported on this vnode, fall back to - * the label in the mount and propagate it to the vnode. - * There should probably be some sort of policy/flag/decision - * about doing this. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - default: + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); return (error); } -} -/* - * Helper function for file systems using the vop_std*_ea() calls. This - * function must be called after EA service is available for the vnode, - * but before it's hooked up to the namespace so that the node persists - * if there's a crash, or before it can be accessed. On successful - * commit of the label to disk (etc), do cache the label. - */ -int -vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) -{ - struct oldmac extmac; - int error; + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); - ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); - if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(tvp, tvp->v_mount); - } else { - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); + if (error == EOPNOTSUPP) + error = 0; /* XXX */ - /* - * Stick the label in the vnode. Then try to write to - * disk. If we fail, return a failure to abort the - * create operation. Really, this failure shouldn't - * happen except in fairly unusual circumstances (out - * of disk, etc). - */ - mac_create_vnode(cred, dvp, tvp); - - error = mac_stdcreatevnode_ea(tvp); - if (error) - return (error); - - /* - * XXX: Eventually this will go away and all policies will - * directly manage their extended attributes. - */ - error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac); - if (error) - return (error); - - error = vn_extattr_set(tvp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); - if (error == 0) - tvp->v_vflag |= VV_CACHEDLABEL; - else { -#if 0 - /* - * In theory, we could have fall-back behavior here. - * It would probably be incorrect. - */ -#endif - return (error); - } - } - - return (0); + return (error); } void mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) { - int error; ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); - error = vn_refreshlabel(vp, old); - if (error) { - printf("mac_execve_transition: vn_refreshlabel returned %d\n", - error); - printf("mac_execve_transition: using old vnode label\n"); - } - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); } int mac_execve_will_transition(struct ucred *old, struct vnode *vp) { - int error, result; - - error = vn_refreshlabel(vp, old); - if (error) - return (error); + int result; result = 0; MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); @@ -2040,10 +1860,6 @@ mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); return (error); } @@ -2058,10 +1874,6 @@ mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); return (error); } @@ -2076,10 +1888,6 @@ mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); return (error); } @@ -2095,10 +1903,6 @@ mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); return (error); } @@ -2115,13 +1919,6 @@ mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2138,10 +1935,6 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); return (error); } @@ -2156,9 +1949,6 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); return (error); @@ -2174,10 +1964,6 @@ mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); return (error); } @@ -2193,10 +1979,6 @@ mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2214,14 +1996,6 @@ mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2238,10 +2012,6 @@ mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); return (error); } @@ -2256,10 +2026,6 @@ mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); return (error); } @@ -2290,10 +2056,6 @@ mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); return (error); } @@ -2308,10 +2070,6 @@ mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); return (error); } @@ -2327,10 +2085,6 @@ mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, &vp->v_label); @@ -2348,10 +2102,6 @@ mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, &vp->v_label); @@ -2368,10 +2118,6 @@ mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); return (error); } @@ -2386,10 +2132,6 @@ mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); return (error); } @@ -2402,10 +2144,6 @@ mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); return (error); @@ -2423,13 +2161,6 @@ mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2447,14 +2178,6 @@ mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - if (vp != NULL) { - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - } MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, vp != NULL ? &vp->v_label : NULL, samedir, cnp); return (error); @@ -2470,10 +2193,6 @@ mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); return (error); } @@ -2489,10 +2208,6 @@ mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); return (error); } @@ -2508,10 +2223,6 @@ mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2527,10 +2238,6 @@ mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); return (error); } @@ -2545,10 +2252,6 @@ mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); return (error); } @@ -2564,10 +2267,6 @@ mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); return (error); } @@ -2583,10 +2282,6 @@ mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, mtime); return (error); @@ -2603,10 +2298,6 @@ mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, &vp->v_label); return (error); @@ -2622,10 +2313,6 @@ mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label); return (error); } @@ -2641,10 +2328,6 @@ mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, &vp->v_label); @@ -3344,7 +3027,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3352,7 +3034,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_ifnet_label(&ifnet->if_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3382,7 +3063,6 @@ mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3444,16 +3124,6 @@ mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, &de->de_label); } -static int -mac_stdcreatevnode_ea(struct vnode *vp) -{ - int error; - - MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); - - return (error); -} - void mac_create_devfs_directory(char *dirname, int dirnamelen, struct devfs_dirent *de) @@ -3463,29 +3133,6 @@ mac_create_devfs_directory(char *dirname, int dirnamelen, &de->de_label); } -/* - * When a new vnode is created, this call will initialize its label. - */ -void -mac_create_vnode(struct ucred *cred, struct vnode *parent, - struct vnode *child) -{ - int error; - - ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); - ASSERT_VOP_LOCKED(child, "mac_create_vnode"); - - error = vn_refreshlabel(parent, cred); - if (error) { - printf("mac_create_vnode: vn_refreshlabel returned %d\n", - error); - printf("mac_create_vnode: using old vnode label\n"); - } - - MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, - &child->v_label); -} - int mac_setsockopt_label_set(struct ucred *cred, struct socket *so, struct mac *mac) @@ -3499,7 +3146,6 @@ mac_setsockopt_label_set(struct ucred *cred, struct socket *so, return (error); buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3554,7 +3200,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3562,7 +3207,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_label(&so->so_label, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3586,7 +3230,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3594,7 +3237,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_peer_label(&so->so_peerlabel, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3616,35 +3258,19 @@ vop_stdsetlabel_ea(struct vop_setlabel_args *ap) { struct vnode *vp = ap->a_vp; struct label *intlabel = ap->a_label; - struct oldmac extmac; int error; ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); - /* - * XXX: Eventually call out to EA check/set calls here. - * Be particularly careful to avoid race conditions, - * consistency problems, and stability problems when - * dealing with multiple EAs. In particular, we require - * the ability to write multiple EAs on the same file in - * a single transaction, which the current EA interface - * does not provide. - */ + if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) + return (EOPNOTSUPP); - error = mac_externalize_vnode_oldmac(intlabel, &extmac); - if (error) - return (error); - - error = vn_extattr_set(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); + error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); if (error) return (error); mac_relabel_vnode(ap->a_cred, vp, intlabel); - vp->v_vflag |= VV_CACHEDLABEL; - return (0); } @@ -3721,7 +3347,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3730,7 +3355,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&tcred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3761,7 +3385,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3769,7 +3392,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&td->td_ucred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3802,7 +3424,6 @@ __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3880,7 +3501,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3888,7 +3508,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ error = fget(td, SCARG(uap, fd), &fp); if (error) @@ -3903,9 +3522,7 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) mac_init_vnode_label(&intlabel); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - error = vn_refreshlabel(vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&vp->v_label, &intlabel); + mac_copy_vnode_label(&vp->v_label, &intlabel); VOP_UNLOCK(vp, 0, td); break; @@ -3974,7 +3591,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3982,7 +3598,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -3991,12 +3606,9 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4034,7 +3646,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -4042,7 +3653,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -4051,12 +3661,9 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4096,7 +3703,6 @@ __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4183,7 +3789,6 @@ __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4240,7 +3845,6 @@ __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c index 78bc485c3863..2ff4162fbfb1 100644 --- a/sys/security/mac/mac_syscalls.c +++ b/sys/security/mac/mac_syscalls.c @@ -115,6 +115,12 @@ SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, */ static int mac_late = 0; +/* + * Warn about EA transactions only the first time they happen. + * Weak coherency, no locking. + */ +static int ea_warn_once = 0; + static int mac_enforce_fs = 1; SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); @@ -145,23 +151,12 @@ SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); -static int mac_label_size = sizeof(struct oldmac); -SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, - &mac_label_size, 0, "Pre-compiled MAC label size"); - static int mac_cache_fslabel_in_vnode = 1; SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); TUNABLE_INT("security.mac.cache_fslabel_in_vnode", &mac_cache_fslabel_in_vnode); -static int mac_vnode_label_cache_hits = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, - &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); -static int mac_vnode_label_cache_misses = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, - &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); - static int mac_mmap_revocation = 1; SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " @@ -214,12 +209,9 @@ SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, #endif static int error_select(int error1, int error2); -static int mac_externalize_vnode_oldmac(struct label *label, - struct oldmac *extmac); static int mac_policy_register(struct mac_policy_conf *mpc); static int mac_policy_unregister(struct mac_policy_conf *mpc); -static int mac_stdcreatevnode_ea(struct vnode *vp); static void mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot); static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, @@ -227,6 +219,10 @@ static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, static void mac_destroy_socket_label(struct label *label); +static int mac_setlabel_vnode_extattr(struct ucred *cred, + struct vnode *vp, struct label *intlabel); + + MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); @@ -623,10 +619,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_externalize_vnode_label = mpe->mpe_function; break; - case MAC_EXTERNALIZE_VNODE_OLDMAC: - mpc->mpc_ops->mpo_externalize_vnode_oldmac = - mpe->mpe_function; - break; case MAC_INTERNALIZE_CRED_LABEL: mpc->mpc_ops->mpo_internalize_cred_label = mpe->mpe_function; @@ -663,14 +655,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_create_devfs_vnode = mpe->mpe_function; break; - case MAC_STDCREATEVNODE_EA: - mpc->mpc_ops->mpo_stdcreatevnode_ea = - mpe->mpe_function; - break; - case MAC_CREATE_VNODE: - mpc->mpc_ops->mpo_create_vnode = - mpe->mpe_function; - break; case MAC_CREATE_MOUNT: mpc->mpc_ops->mpo_create_mount = mpe->mpe_function; @@ -687,20 +671,24 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_update_devfsdirent = mpe->mpe_function; break; - case MAC_UPDATE_PROCFSVNODE: - mpc->mpc_ops->mpo_update_procfsvnode = + case MAC_ASSOCIATE_VNODE_DEVFS: + mpc->mpc_ops->mpo_associate_vnode_devfs = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTATTR: - mpc->mpc_ops->mpo_update_vnode_from_extattr = + case MAC_ASSOCIATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_associate_vnode_extattr = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: - mpc->mpc_ops->mpo_update_vnode_from_externalized = + case MAC_ASSOCIATE_VNODE_SINGLELABEL: + mpc->mpc_ops->mpo_associate_vnode_singlelabel = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_MOUNT: - mpc->mpc_ops->mpo_update_vnode_from_mount = + case MAC_CREATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_create_vnode_extattr = + mpe->mpe_function; + break; + case MAC_SETLABEL_VNODE_EXTATTR: + mpc->mpc_ops->mpo_setlabel_vnode_extattr = mpe->mpe_function; break; case MAC_CREATE_MBUF_FROM_SOCKET: @@ -1379,7 +1367,7 @@ mac_init_socket(struct socket *socket, int flag) return (error); } -static void +void mac_init_vnode_label(struct label *label) { @@ -1536,7 +1524,7 @@ mac_destroy_socket(struct socket *socket) mac_destroy_socket_peer_label(&socket->so_peerlabel); } -static void +void mac_destroy_vnode_label(struct label *label) { @@ -1561,7 +1549,7 @@ mac_copy_pipe_label(struct label *src, struct label *dest) MAC_PERFORM(copy_pipe_label, src, dest); } -static void +void mac_copy_vnode_label(struct label *src, struct label *dest) { @@ -1644,16 +1632,6 @@ mac_externalize_vnode_label(struct label *label, char *elements, return (error); } -static int -mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(externalize_vnode_oldmac, label, extmac); - - return (error); -} - static int mac_internalize_cred_label(struct label *label, char *string) { @@ -1753,276 +1731,118 @@ mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) } void -mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) +mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, + struct vnode *vp) { - MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); + MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, + &de->de_label, vp, &vp->v_label); } -/* - * Support callout for policies that manage their own externalization - * using extended attributes. - */ -static int -mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) +int +mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) { int error; - MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, - &mp->mnt_fslabel); + ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); + + MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, + &vp->v_label); return (error); } -/* - * Given an externalized mac label, internalize it and stamp it on a - * vnode. - */ -static int -mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); - - return (error); -} - -/* - * Call out to individual policies to update the label in a vnode from - * the mountpoint. - */ void -mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) +mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) { - MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, - &mp->mnt_fslabel); - - ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); - if (mac_cache_fslabel_in_vnode) - vp->v_vflag |= VV_CACHEDLABEL; + MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, + &vp->v_label); } -/* - * Implementation of VOP_REFRESHLABEL() that relies on extended attributes - * to store label data. Can be referenced by filesystems supporting - * extended attributes. - */ int -vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) +mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { - struct vnode *vp = ap->a_vp; - struct oldmac extmac; - int buflen, error; + int error; - ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); + ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); + ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); - /* - * Call out to external policies first. Order doesn't really - * matter, as long as failure of one assures failure of all. - */ - error = mac_update_vnode_from_extattr(vp, vp->v_mount); - if (error) - return (error); - - buflen = sizeof(extmac); - error = vn_extattr_get(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, - (char *)&extmac, curthread); - switch (error) { - case 0: - /* Got it */ - break; - - case ENOATTR: - /* - * Use the label from the mount point. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - - case EOPNOTSUPP: - default: - /* Fail horribly. */ - return (error); - } - - if (buflen != sizeof(extmac)) - error = EPERM; /* Fail very closed. */ - if (error == 0) - error = mac_update_vnode_from_externalized(vp, &extmac); - if (error == 0) - vp->v_vflag |= VV_CACHEDLABEL; - else { - struct vattr va; - - printf("Corrupted label on %s", - vp->v_mount->mnt_stat.f_mntonname); - if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) - printf(" inum %ld", va.va_fileid); -#ifdef MAC_DEBUG - if (mac_debug_label_fallback) { - printf(", falling back.\n"); - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - } else { -#endif - printf(".\n"); - error = EPERM; -#ifdef MAC_DEBUG + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; } -#endif + } else if (error) + return (error); + + MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, + dvp, &dvp->v_label, vp, &vp->v_label, cnp); + + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); + return (error); } + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); + + if (error == EOPNOTSUPP) + error = 0; /* XXX */ + return (error); } -/* - * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle - * the labeling activity outselves. Filesystems should be careful not - * to change their minds regarding whether they support vop_refreshlabel() - * for a vnode or not. Don't cache the vnode here, allow the file - * system code to determine if it's safe to cache. If we update from - * the mount, don't cache since a change to the mount label should affect - * all vnodes. - */ static int -vn_refreshlabel(struct vnode *vp, struct ucred *cred) +mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *intlabel) { int error; - ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); + ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); - if (vp->v_mount == NULL) { -/* - Eventually, we probably want to special-case refreshing - of deadfs vnodes, and if there's a lock-free race somewhere, - that case might be handled here. + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; + } + } else if (error) + return (error); - mac_update_vnode_deadfs(vp); - return (0); - */ - /* printf("vn_refreshlabel: null v_mount\n"); */ - if (vp->v_type != VNON) - printf( - "vn_refreshlabel: null v_mount with non-VNON\n"); - return (EBADF); - } + MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); - if (vp->v_vflag & VV_CACHEDLABEL) { - mac_vnode_label_cache_hits++; - return (0); - } else - mac_vnode_label_cache_misses++; - - if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - } - - error = VOP_REFRESHLABEL(vp, cred, curthread); - switch (error) { - case EOPNOTSUPP: - /* - * If labels are not supported on this vnode, fall back to - * the label in the mount and propagate it to the vnode. - * There should probably be some sort of policy/flag/decision - * about doing this. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - default: + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); return (error); } -} -/* - * Helper function for file systems using the vop_std*_ea() calls. This - * function must be called after EA service is available for the vnode, - * but before it's hooked up to the namespace so that the node persists - * if there's a crash, or before it can be accessed. On successful - * commit of the label to disk (etc), do cache the label. - */ -int -vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) -{ - struct oldmac extmac; - int error; + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); - ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); - if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(tvp, tvp->v_mount); - } else { - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); + if (error == EOPNOTSUPP) + error = 0; /* XXX */ - /* - * Stick the label in the vnode. Then try to write to - * disk. If we fail, return a failure to abort the - * create operation. Really, this failure shouldn't - * happen except in fairly unusual circumstances (out - * of disk, etc). - */ - mac_create_vnode(cred, dvp, tvp); - - error = mac_stdcreatevnode_ea(tvp); - if (error) - return (error); - - /* - * XXX: Eventually this will go away and all policies will - * directly manage their extended attributes. - */ - error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac); - if (error) - return (error); - - error = vn_extattr_set(tvp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); - if (error == 0) - tvp->v_vflag |= VV_CACHEDLABEL; - else { -#if 0 - /* - * In theory, we could have fall-back behavior here. - * It would probably be incorrect. - */ -#endif - return (error); - } - } - - return (0); + return (error); } void mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) { - int error; ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); - error = vn_refreshlabel(vp, old); - if (error) { - printf("mac_execve_transition: vn_refreshlabel returned %d\n", - error); - printf("mac_execve_transition: using old vnode label\n"); - } - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); } int mac_execve_will_transition(struct ucred *old, struct vnode *vp) { - int error, result; - - error = vn_refreshlabel(vp, old); - if (error) - return (error); + int result; result = 0; MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); @@ -2040,10 +1860,6 @@ mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); return (error); } @@ -2058,10 +1874,6 @@ mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); return (error); } @@ -2076,10 +1888,6 @@ mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); return (error); } @@ -2095,10 +1903,6 @@ mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); return (error); } @@ -2115,13 +1919,6 @@ mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2138,10 +1935,6 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); return (error); } @@ -2156,9 +1949,6 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); return (error); @@ -2174,10 +1964,6 @@ mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); return (error); } @@ -2193,10 +1979,6 @@ mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2214,14 +1996,6 @@ mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2238,10 +2012,6 @@ mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); return (error); } @@ -2256,10 +2026,6 @@ mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); return (error); } @@ -2290,10 +2056,6 @@ mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); return (error); } @@ -2308,10 +2070,6 @@ mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); return (error); } @@ -2327,10 +2085,6 @@ mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, &vp->v_label); @@ -2348,10 +2102,6 @@ mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, &vp->v_label); @@ -2368,10 +2118,6 @@ mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); return (error); } @@ -2386,10 +2132,6 @@ mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); return (error); } @@ -2402,10 +2144,6 @@ mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); return (error); @@ -2423,13 +2161,6 @@ mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2447,14 +2178,6 @@ mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - if (vp != NULL) { - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - } MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, vp != NULL ? &vp->v_label : NULL, samedir, cnp); return (error); @@ -2470,10 +2193,6 @@ mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); return (error); } @@ -2489,10 +2208,6 @@ mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); return (error); } @@ -2508,10 +2223,6 @@ mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2527,10 +2238,6 @@ mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); return (error); } @@ -2545,10 +2252,6 @@ mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); return (error); } @@ -2564,10 +2267,6 @@ mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); return (error); } @@ -2583,10 +2282,6 @@ mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, mtime); return (error); @@ -2603,10 +2298,6 @@ mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, &vp->v_label); return (error); @@ -2622,10 +2313,6 @@ mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label); return (error); } @@ -2641,10 +2328,6 @@ mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, &vp->v_label); @@ -3344,7 +3027,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3352,7 +3034,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_ifnet_label(&ifnet->if_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3382,7 +3063,6 @@ mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3444,16 +3124,6 @@ mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, &de->de_label); } -static int -mac_stdcreatevnode_ea(struct vnode *vp) -{ - int error; - - MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); - - return (error); -} - void mac_create_devfs_directory(char *dirname, int dirnamelen, struct devfs_dirent *de) @@ -3463,29 +3133,6 @@ mac_create_devfs_directory(char *dirname, int dirnamelen, &de->de_label); } -/* - * When a new vnode is created, this call will initialize its label. - */ -void -mac_create_vnode(struct ucred *cred, struct vnode *parent, - struct vnode *child) -{ - int error; - - ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); - ASSERT_VOP_LOCKED(child, "mac_create_vnode"); - - error = vn_refreshlabel(parent, cred); - if (error) { - printf("mac_create_vnode: vn_refreshlabel returned %d\n", - error); - printf("mac_create_vnode: using old vnode label\n"); - } - - MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, - &child->v_label); -} - int mac_setsockopt_label_set(struct ucred *cred, struct socket *so, struct mac *mac) @@ -3499,7 +3146,6 @@ mac_setsockopt_label_set(struct ucred *cred, struct socket *so, return (error); buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3554,7 +3200,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3562,7 +3207,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_label(&so->so_label, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3586,7 +3230,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3594,7 +3237,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_peer_label(&so->so_peerlabel, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3616,35 +3258,19 @@ vop_stdsetlabel_ea(struct vop_setlabel_args *ap) { struct vnode *vp = ap->a_vp; struct label *intlabel = ap->a_label; - struct oldmac extmac; int error; ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); - /* - * XXX: Eventually call out to EA check/set calls here. - * Be particularly careful to avoid race conditions, - * consistency problems, and stability problems when - * dealing with multiple EAs. In particular, we require - * the ability to write multiple EAs on the same file in - * a single transaction, which the current EA interface - * does not provide. - */ + if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) + return (EOPNOTSUPP); - error = mac_externalize_vnode_oldmac(intlabel, &extmac); - if (error) - return (error); - - error = vn_extattr_set(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); + error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); if (error) return (error); mac_relabel_vnode(ap->a_cred, vp, intlabel); - vp->v_vflag |= VV_CACHEDLABEL; - return (0); } @@ -3721,7 +3347,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3730,7 +3355,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&tcred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3761,7 +3385,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3769,7 +3392,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&td->td_ucred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3802,7 +3424,6 @@ __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3880,7 +3501,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3888,7 +3508,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ error = fget(td, SCARG(uap, fd), &fp); if (error) @@ -3903,9 +3522,7 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) mac_init_vnode_label(&intlabel); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - error = vn_refreshlabel(vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&vp->v_label, &intlabel); + mac_copy_vnode_label(&vp->v_label, &intlabel); VOP_UNLOCK(vp, 0, td); break; @@ -3974,7 +3591,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3982,7 +3598,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -3991,12 +3606,9 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4034,7 +3646,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -4042,7 +3653,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -4051,12 +3661,9 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4096,7 +3703,6 @@ __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4183,7 +3789,6 @@ __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4240,7 +3845,6 @@ __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); diff --git a/sys/security/mac/mac_system.c b/sys/security/mac/mac_system.c index 78bc485c3863..2ff4162fbfb1 100644 --- a/sys/security/mac/mac_system.c +++ b/sys/security/mac/mac_system.c @@ -115,6 +115,12 @@ SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, */ static int mac_late = 0; +/* + * Warn about EA transactions only the first time they happen. + * Weak coherency, no locking. + */ +static int ea_warn_once = 0; + static int mac_enforce_fs = 1; SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); @@ -145,23 +151,12 @@ SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); -static int mac_label_size = sizeof(struct oldmac); -SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, - &mac_label_size, 0, "Pre-compiled MAC label size"); - static int mac_cache_fslabel_in_vnode = 1; SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); TUNABLE_INT("security.mac.cache_fslabel_in_vnode", &mac_cache_fslabel_in_vnode); -static int mac_vnode_label_cache_hits = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, - &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); -static int mac_vnode_label_cache_misses = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, - &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); - static int mac_mmap_revocation = 1; SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " @@ -214,12 +209,9 @@ SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, #endif static int error_select(int error1, int error2); -static int mac_externalize_vnode_oldmac(struct label *label, - struct oldmac *extmac); static int mac_policy_register(struct mac_policy_conf *mpc); static int mac_policy_unregister(struct mac_policy_conf *mpc); -static int mac_stdcreatevnode_ea(struct vnode *vp); static void mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot); static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, @@ -227,6 +219,10 @@ static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, static void mac_destroy_socket_label(struct label *label); +static int mac_setlabel_vnode_extattr(struct ucred *cred, + struct vnode *vp, struct label *intlabel); + + MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); @@ -623,10 +619,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_externalize_vnode_label = mpe->mpe_function; break; - case MAC_EXTERNALIZE_VNODE_OLDMAC: - mpc->mpc_ops->mpo_externalize_vnode_oldmac = - mpe->mpe_function; - break; case MAC_INTERNALIZE_CRED_LABEL: mpc->mpc_ops->mpo_internalize_cred_label = mpe->mpe_function; @@ -663,14 +655,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_create_devfs_vnode = mpe->mpe_function; break; - case MAC_STDCREATEVNODE_EA: - mpc->mpc_ops->mpo_stdcreatevnode_ea = - mpe->mpe_function; - break; - case MAC_CREATE_VNODE: - mpc->mpc_ops->mpo_create_vnode = - mpe->mpe_function; - break; case MAC_CREATE_MOUNT: mpc->mpc_ops->mpo_create_mount = mpe->mpe_function; @@ -687,20 +671,24 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_update_devfsdirent = mpe->mpe_function; break; - case MAC_UPDATE_PROCFSVNODE: - mpc->mpc_ops->mpo_update_procfsvnode = + case MAC_ASSOCIATE_VNODE_DEVFS: + mpc->mpc_ops->mpo_associate_vnode_devfs = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTATTR: - mpc->mpc_ops->mpo_update_vnode_from_extattr = + case MAC_ASSOCIATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_associate_vnode_extattr = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: - mpc->mpc_ops->mpo_update_vnode_from_externalized = + case MAC_ASSOCIATE_VNODE_SINGLELABEL: + mpc->mpc_ops->mpo_associate_vnode_singlelabel = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_MOUNT: - mpc->mpc_ops->mpo_update_vnode_from_mount = + case MAC_CREATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_create_vnode_extattr = + mpe->mpe_function; + break; + case MAC_SETLABEL_VNODE_EXTATTR: + mpc->mpc_ops->mpo_setlabel_vnode_extattr = mpe->mpe_function; break; case MAC_CREATE_MBUF_FROM_SOCKET: @@ -1379,7 +1367,7 @@ mac_init_socket(struct socket *socket, int flag) return (error); } -static void +void mac_init_vnode_label(struct label *label) { @@ -1536,7 +1524,7 @@ mac_destroy_socket(struct socket *socket) mac_destroy_socket_peer_label(&socket->so_peerlabel); } -static void +void mac_destroy_vnode_label(struct label *label) { @@ -1561,7 +1549,7 @@ mac_copy_pipe_label(struct label *src, struct label *dest) MAC_PERFORM(copy_pipe_label, src, dest); } -static void +void mac_copy_vnode_label(struct label *src, struct label *dest) { @@ -1644,16 +1632,6 @@ mac_externalize_vnode_label(struct label *label, char *elements, return (error); } -static int -mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(externalize_vnode_oldmac, label, extmac); - - return (error); -} - static int mac_internalize_cred_label(struct label *label, char *string) { @@ -1753,276 +1731,118 @@ mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) } void -mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) +mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, + struct vnode *vp) { - MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); + MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, + &de->de_label, vp, &vp->v_label); } -/* - * Support callout for policies that manage their own externalization - * using extended attributes. - */ -static int -mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) +int +mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) { int error; - MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, - &mp->mnt_fslabel); + ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); + + MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, + &vp->v_label); return (error); } -/* - * Given an externalized mac label, internalize it and stamp it on a - * vnode. - */ -static int -mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); - - return (error); -} - -/* - * Call out to individual policies to update the label in a vnode from - * the mountpoint. - */ void -mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) +mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) { - MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, - &mp->mnt_fslabel); - - ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); - if (mac_cache_fslabel_in_vnode) - vp->v_vflag |= VV_CACHEDLABEL; + MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, + &vp->v_label); } -/* - * Implementation of VOP_REFRESHLABEL() that relies on extended attributes - * to store label data. Can be referenced by filesystems supporting - * extended attributes. - */ int -vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) +mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { - struct vnode *vp = ap->a_vp; - struct oldmac extmac; - int buflen, error; + int error; - ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); + ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); + ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); - /* - * Call out to external policies first. Order doesn't really - * matter, as long as failure of one assures failure of all. - */ - error = mac_update_vnode_from_extattr(vp, vp->v_mount); - if (error) - return (error); - - buflen = sizeof(extmac); - error = vn_extattr_get(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, - (char *)&extmac, curthread); - switch (error) { - case 0: - /* Got it */ - break; - - case ENOATTR: - /* - * Use the label from the mount point. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - - case EOPNOTSUPP: - default: - /* Fail horribly. */ - return (error); - } - - if (buflen != sizeof(extmac)) - error = EPERM; /* Fail very closed. */ - if (error == 0) - error = mac_update_vnode_from_externalized(vp, &extmac); - if (error == 0) - vp->v_vflag |= VV_CACHEDLABEL; - else { - struct vattr va; - - printf("Corrupted label on %s", - vp->v_mount->mnt_stat.f_mntonname); - if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) - printf(" inum %ld", va.va_fileid); -#ifdef MAC_DEBUG - if (mac_debug_label_fallback) { - printf(", falling back.\n"); - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - } else { -#endif - printf(".\n"); - error = EPERM; -#ifdef MAC_DEBUG + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; } -#endif + } else if (error) + return (error); + + MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, + dvp, &dvp->v_label, vp, &vp->v_label, cnp); + + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); + return (error); } + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); + + if (error == EOPNOTSUPP) + error = 0; /* XXX */ + return (error); } -/* - * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle - * the labeling activity outselves. Filesystems should be careful not - * to change their minds regarding whether they support vop_refreshlabel() - * for a vnode or not. Don't cache the vnode here, allow the file - * system code to determine if it's safe to cache. If we update from - * the mount, don't cache since a change to the mount label should affect - * all vnodes. - */ static int -vn_refreshlabel(struct vnode *vp, struct ucred *cred) +mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *intlabel) { int error; - ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); + ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); - if (vp->v_mount == NULL) { -/* - Eventually, we probably want to special-case refreshing - of deadfs vnodes, and if there's a lock-free race somewhere, - that case might be handled here. + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; + } + } else if (error) + return (error); - mac_update_vnode_deadfs(vp); - return (0); - */ - /* printf("vn_refreshlabel: null v_mount\n"); */ - if (vp->v_type != VNON) - printf( - "vn_refreshlabel: null v_mount with non-VNON\n"); - return (EBADF); - } + MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); - if (vp->v_vflag & VV_CACHEDLABEL) { - mac_vnode_label_cache_hits++; - return (0); - } else - mac_vnode_label_cache_misses++; - - if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - } - - error = VOP_REFRESHLABEL(vp, cred, curthread); - switch (error) { - case EOPNOTSUPP: - /* - * If labels are not supported on this vnode, fall back to - * the label in the mount and propagate it to the vnode. - * There should probably be some sort of policy/flag/decision - * about doing this. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - default: + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); return (error); } -} -/* - * Helper function for file systems using the vop_std*_ea() calls. This - * function must be called after EA service is available for the vnode, - * but before it's hooked up to the namespace so that the node persists - * if there's a crash, or before it can be accessed. On successful - * commit of the label to disk (etc), do cache the label. - */ -int -vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) -{ - struct oldmac extmac; - int error; + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); - ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); - if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(tvp, tvp->v_mount); - } else { - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); + if (error == EOPNOTSUPP) + error = 0; /* XXX */ - /* - * Stick the label in the vnode. Then try to write to - * disk. If we fail, return a failure to abort the - * create operation. Really, this failure shouldn't - * happen except in fairly unusual circumstances (out - * of disk, etc). - */ - mac_create_vnode(cred, dvp, tvp); - - error = mac_stdcreatevnode_ea(tvp); - if (error) - return (error); - - /* - * XXX: Eventually this will go away and all policies will - * directly manage their extended attributes. - */ - error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac); - if (error) - return (error); - - error = vn_extattr_set(tvp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); - if (error == 0) - tvp->v_vflag |= VV_CACHEDLABEL; - else { -#if 0 - /* - * In theory, we could have fall-back behavior here. - * It would probably be incorrect. - */ -#endif - return (error); - } - } - - return (0); + return (error); } void mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) { - int error; ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); - error = vn_refreshlabel(vp, old); - if (error) { - printf("mac_execve_transition: vn_refreshlabel returned %d\n", - error); - printf("mac_execve_transition: using old vnode label\n"); - } - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); } int mac_execve_will_transition(struct ucred *old, struct vnode *vp) { - int error, result; - - error = vn_refreshlabel(vp, old); - if (error) - return (error); + int result; result = 0; MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); @@ -2040,10 +1860,6 @@ mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); return (error); } @@ -2058,10 +1874,6 @@ mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); return (error); } @@ -2076,10 +1888,6 @@ mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); return (error); } @@ -2095,10 +1903,6 @@ mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); return (error); } @@ -2115,13 +1919,6 @@ mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2138,10 +1935,6 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); return (error); } @@ -2156,9 +1949,6 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); return (error); @@ -2174,10 +1964,6 @@ mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); return (error); } @@ -2193,10 +1979,6 @@ mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2214,14 +1996,6 @@ mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2238,10 +2012,6 @@ mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); return (error); } @@ -2256,10 +2026,6 @@ mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); return (error); } @@ -2290,10 +2056,6 @@ mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); return (error); } @@ -2308,10 +2070,6 @@ mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); return (error); } @@ -2327,10 +2085,6 @@ mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, &vp->v_label); @@ -2348,10 +2102,6 @@ mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, &vp->v_label); @@ -2368,10 +2118,6 @@ mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); return (error); } @@ -2386,10 +2132,6 @@ mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); return (error); } @@ -2402,10 +2144,6 @@ mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); return (error); @@ -2423,13 +2161,6 @@ mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2447,14 +2178,6 @@ mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - if (vp != NULL) { - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - } MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, vp != NULL ? &vp->v_label : NULL, samedir, cnp); return (error); @@ -2470,10 +2193,6 @@ mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); return (error); } @@ -2489,10 +2208,6 @@ mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); return (error); } @@ -2508,10 +2223,6 @@ mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2527,10 +2238,6 @@ mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); return (error); } @@ -2545,10 +2252,6 @@ mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); return (error); } @@ -2564,10 +2267,6 @@ mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); return (error); } @@ -2583,10 +2282,6 @@ mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, mtime); return (error); @@ -2603,10 +2298,6 @@ mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, &vp->v_label); return (error); @@ -2622,10 +2313,6 @@ mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label); return (error); } @@ -2641,10 +2328,6 @@ mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, &vp->v_label); @@ -3344,7 +3027,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3352,7 +3034,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_ifnet_label(&ifnet->if_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3382,7 +3063,6 @@ mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3444,16 +3124,6 @@ mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, &de->de_label); } -static int -mac_stdcreatevnode_ea(struct vnode *vp) -{ - int error; - - MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); - - return (error); -} - void mac_create_devfs_directory(char *dirname, int dirnamelen, struct devfs_dirent *de) @@ -3463,29 +3133,6 @@ mac_create_devfs_directory(char *dirname, int dirnamelen, &de->de_label); } -/* - * When a new vnode is created, this call will initialize its label. - */ -void -mac_create_vnode(struct ucred *cred, struct vnode *parent, - struct vnode *child) -{ - int error; - - ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); - ASSERT_VOP_LOCKED(child, "mac_create_vnode"); - - error = vn_refreshlabel(parent, cred); - if (error) { - printf("mac_create_vnode: vn_refreshlabel returned %d\n", - error); - printf("mac_create_vnode: using old vnode label\n"); - } - - MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, - &child->v_label); -} - int mac_setsockopt_label_set(struct ucred *cred, struct socket *so, struct mac *mac) @@ -3499,7 +3146,6 @@ mac_setsockopt_label_set(struct ucred *cred, struct socket *so, return (error); buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3554,7 +3200,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3562,7 +3207,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_label(&so->so_label, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3586,7 +3230,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3594,7 +3237,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_peer_label(&so->so_peerlabel, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3616,35 +3258,19 @@ vop_stdsetlabel_ea(struct vop_setlabel_args *ap) { struct vnode *vp = ap->a_vp; struct label *intlabel = ap->a_label; - struct oldmac extmac; int error; ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); - /* - * XXX: Eventually call out to EA check/set calls here. - * Be particularly careful to avoid race conditions, - * consistency problems, and stability problems when - * dealing with multiple EAs. In particular, we require - * the ability to write multiple EAs on the same file in - * a single transaction, which the current EA interface - * does not provide. - */ + if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) + return (EOPNOTSUPP); - error = mac_externalize_vnode_oldmac(intlabel, &extmac); - if (error) - return (error); - - error = vn_extattr_set(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); + error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); if (error) return (error); mac_relabel_vnode(ap->a_cred, vp, intlabel); - vp->v_vflag |= VV_CACHEDLABEL; - return (0); } @@ -3721,7 +3347,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3730,7 +3355,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&tcred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3761,7 +3385,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3769,7 +3392,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&td->td_ucred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3802,7 +3424,6 @@ __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3880,7 +3501,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3888,7 +3508,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ error = fget(td, SCARG(uap, fd), &fp); if (error) @@ -3903,9 +3522,7 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) mac_init_vnode_label(&intlabel); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - error = vn_refreshlabel(vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&vp->v_label, &intlabel); + mac_copy_vnode_label(&vp->v_label, &intlabel); VOP_UNLOCK(vp, 0, td); break; @@ -3974,7 +3591,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3982,7 +3598,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -3991,12 +3606,9 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4034,7 +3646,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -4042,7 +3653,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -4051,12 +3661,9 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4096,7 +3703,6 @@ __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4183,7 +3789,6 @@ __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4240,7 +3845,6 @@ __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); diff --git a/sys/security/mac/mac_vfs.c b/sys/security/mac/mac_vfs.c index 78bc485c3863..2ff4162fbfb1 100644 --- a/sys/security/mac/mac_vfs.c +++ b/sys/security/mac/mac_vfs.c @@ -115,6 +115,12 @@ SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD, */ static int mac_late = 0; +/* + * Warn about EA transactions only the first time they happen. + * Weak coherency, no locking. + */ +static int ea_warn_once = 0; + static int mac_enforce_fs = 1; SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW, &mac_enforce_fs, 0, "Enforce MAC policy on file system objects"); @@ -145,23 +151,12 @@ SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW, &mac_enforce_vm, 0, "Enforce MAC policy on vm operations"); TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm); -static int mac_label_size = sizeof(struct oldmac); -SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD, - &mac_label_size, 0, "Pre-compiled MAC label size"); - static int mac_cache_fslabel_in_vnode = 1; SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW, &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode"); TUNABLE_INT("security.mac.cache_fslabel_in_vnode", &mac_cache_fslabel_in_vnode); -static int mac_vnode_label_cache_hits = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD, - &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels"); -static int mac_vnode_label_cache_misses = 0; -SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD, - &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels"); - static int mac_mmap_revocation = 1; SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW, &mac_mmap_revocation, 0, "Revoke mmap access to files on subject " @@ -214,12 +209,9 @@ SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD, #endif static int error_select(int error1, int error2); -static int mac_externalize_vnode_oldmac(struct label *label, - struct oldmac *extmac); static int mac_policy_register(struct mac_policy_conf *mpc); static int mac_policy_unregister(struct mac_policy_conf *mpc); -static int mac_stdcreatevnode_ea(struct vnode *vp); static void mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot); static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, @@ -227,6 +219,10 @@ static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, static void mac_destroy_socket_label(struct label *label); +static int mac_setlabel_vnode_extattr(struct ucred *cred, + struct vnode *vp, struct label *intlabel); + + MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector"); MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes"); MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage"); @@ -623,10 +619,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_externalize_vnode_label = mpe->mpe_function; break; - case MAC_EXTERNALIZE_VNODE_OLDMAC: - mpc->mpc_ops->mpo_externalize_vnode_oldmac = - mpe->mpe_function; - break; case MAC_INTERNALIZE_CRED_LABEL: mpc->mpc_ops->mpo_internalize_cred_label = mpe->mpe_function; @@ -663,14 +655,6 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_create_devfs_vnode = mpe->mpe_function; break; - case MAC_STDCREATEVNODE_EA: - mpc->mpc_ops->mpo_stdcreatevnode_ea = - mpe->mpe_function; - break; - case MAC_CREATE_VNODE: - mpc->mpc_ops->mpo_create_vnode = - mpe->mpe_function; - break; case MAC_CREATE_MOUNT: mpc->mpc_ops->mpo_create_mount = mpe->mpe_function; @@ -687,20 +671,24 @@ mac_policy_register(struct mac_policy_conf *mpc) mpc->mpc_ops->mpo_update_devfsdirent = mpe->mpe_function; break; - case MAC_UPDATE_PROCFSVNODE: - mpc->mpc_ops->mpo_update_procfsvnode = + case MAC_ASSOCIATE_VNODE_DEVFS: + mpc->mpc_ops->mpo_associate_vnode_devfs = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTATTR: - mpc->mpc_ops->mpo_update_vnode_from_extattr = + case MAC_ASSOCIATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_associate_vnode_extattr = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_EXTERNALIZED: - mpc->mpc_ops->mpo_update_vnode_from_externalized = + case MAC_ASSOCIATE_VNODE_SINGLELABEL: + mpc->mpc_ops->mpo_associate_vnode_singlelabel = mpe->mpe_function; break; - case MAC_UPDATE_VNODE_FROM_MOUNT: - mpc->mpc_ops->mpo_update_vnode_from_mount = + case MAC_CREATE_VNODE_EXTATTR: + mpc->mpc_ops->mpo_create_vnode_extattr = + mpe->mpe_function; + break; + case MAC_SETLABEL_VNODE_EXTATTR: + mpc->mpc_ops->mpo_setlabel_vnode_extattr = mpe->mpe_function; break; case MAC_CREATE_MBUF_FROM_SOCKET: @@ -1379,7 +1367,7 @@ mac_init_socket(struct socket *socket, int flag) return (error); } -static void +void mac_init_vnode_label(struct label *label) { @@ -1536,7 +1524,7 @@ mac_destroy_socket(struct socket *socket) mac_destroy_socket_peer_label(&socket->so_peerlabel); } -static void +void mac_destroy_vnode_label(struct label *label) { @@ -1561,7 +1549,7 @@ mac_copy_pipe_label(struct label *src, struct label *dest) MAC_PERFORM(copy_pipe_label, src, dest); } -static void +void mac_copy_vnode_label(struct label *src, struct label *dest) { @@ -1644,16 +1632,6 @@ mac_externalize_vnode_label(struct label *label, char *elements, return (error); } -static int -mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(externalize_vnode_oldmac, label, extmac); - - return (error); -} - static int mac_internalize_cred_label(struct label *label, char *string) { @@ -1753,276 +1731,118 @@ mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp) } void -mac_update_procfsvnode(struct vnode *vp, struct ucred *cred) +mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, + struct vnode *vp) { - MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred); + MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de, + &de->de_label, vp, &vp->v_label); } -/* - * Support callout for policies that manage their own externalization - * using extended attributes. - */ -static int -mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp) +int +mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp) { int error; - MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp, - &mp->mnt_fslabel); + ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr"); + + MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp, + &vp->v_label); return (error); } -/* - * Given an externalized mac label, internalize it and stamp it on a - * vnode. - */ -static int -mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac) -{ - int error; - - MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac); - - return (error); -} - -/* - * Call out to individual policies to update the label in a vnode from - * the mountpoint. - */ void -mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp) +mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp) { - MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp, - &mp->mnt_fslabel); - - ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount"); - if (mac_cache_fslabel_in_vnode) - vp->v_vflag |= VV_CACHEDLABEL; + MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp, + &vp->v_label); } -/* - * Implementation of VOP_REFRESHLABEL() that relies on extended attributes - * to store label data. Can be referenced by filesystems supporting - * extended attributes. - */ int -vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap) +mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { - struct vnode *vp = ap->a_vp; - struct oldmac extmac; - int buflen, error; + int error; - ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea"); + ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr"); + ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr"); - /* - * Call out to external policies first. Order doesn't really - * matter, as long as failure of one assures failure of all. - */ - error = mac_update_vnode_from_extattr(vp, vp->v_mount); - if (error) - return (error); - - buflen = sizeof(extmac); - error = vn_extattr_get(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen, - (char *)&extmac, curthread); - switch (error) { - case 0: - /* Got it */ - break; - - case ENOATTR: - /* - * Use the label from the mount point. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - - case EOPNOTSUPP: - default: - /* Fail horribly. */ - return (error); - } - - if (buflen != sizeof(extmac)) - error = EPERM; /* Fail very closed. */ - if (error == 0) - error = mac_update_vnode_from_externalized(vp, &extmac); - if (error == 0) - vp->v_vflag |= VV_CACHEDLABEL; - else { - struct vattr va; - - printf("Corrupted label on %s", - vp->v_mount->mnt_stat.f_mntonname); - if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0) - printf(" inum %ld", va.va_fileid); -#ifdef MAC_DEBUG - if (mac_debug_label_fallback) { - printf(", falling back.\n"); - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - } else { -#endif - printf(".\n"); - error = EPERM; -#ifdef MAC_DEBUG + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; } -#endif + } else if (error) + return (error); + + MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel, + dvp, &dvp->v_label, vp, &vp->v_label, cnp); + + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); + return (error); } + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); + + if (error == EOPNOTSUPP) + error = 0; /* XXX */ + return (error); } -/* - * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle - * the labeling activity outselves. Filesystems should be careful not - * to change their minds regarding whether they support vop_refreshlabel() - * for a vnode or not. Don't cache the vnode here, allow the file - * system code to determine if it's safe to cache. If we update from - * the mount, don't cache since a change to the mount label should affect - * all vnodes. - */ static int -vn_refreshlabel(struct vnode *vp, struct ucred *cred) +mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *intlabel) { int error; - ASSERT_VOP_LOCKED(vp, "vn_refreshlabel"); + ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr"); - if (vp->v_mount == NULL) { -/* - Eventually, we probably want to special-case refreshing - of deadfs vnodes, and if there's a lock-free race somewhere, - that case might be handled here. + error = VOP_OPENEXTATTR(vp, cred, curthread); + if (error == EOPNOTSUPP) { + /* XXX: Optionally abort if transactions not supported. */ + if (ea_warn_once == 0) { + printf("Warning: transactions not supported " + "in EA write.\n"); + ea_warn_once = 1; + } + } else if (error) + return (error); - mac_update_vnode_deadfs(vp); - return (0); - */ - /* printf("vn_refreshlabel: null v_mount\n"); */ - if (vp->v_type != VNON) - printf( - "vn_refreshlabel: null v_mount with non-VNON\n"); - return (EBADF); - } + MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel); - if (vp->v_vflag & VV_CACHEDLABEL) { - mac_vnode_label_cache_hits++; - return (0); - } else - mac_vnode_label_cache_misses++; - - if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(vp, vp->v_mount); - return (0); - } - - error = VOP_REFRESHLABEL(vp, cred, curthread); - switch (error) { - case EOPNOTSUPP: - /* - * If labels are not supported on this vnode, fall back to - * the label in the mount and propagate it to the vnode. - * There should probably be some sort of policy/flag/decision - * about doing this. - */ - mac_update_vnode_from_mount(vp, vp->v_mount); - error = 0; - default: + if (error) { + VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread); return (error); } -} -/* - * Helper function for file systems using the vop_std*_ea() calls. This - * function must be called after EA service is available for the vnode, - * but before it's hooked up to the namespace so that the node persists - * if there's a crash, or before it can be accessed. On successful - * commit of the label to disk (etc), do cache the label. - */ -int -vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred) -{ - struct oldmac extmac; - int error; + error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread); - ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea"); - if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { - mac_update_vnode_from_mount(tvp, tvp->v_mount); - } else { - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); + if (error == EOPNOTSUPP) + error = 0; /* XXX */ - /* - * Stick the label in the vnode. Then try to write to - * disk. If we fail, return a failure to abort the - * create operation. Really, this failure shouldn't - * happen except in fairly unusual circumstances (out - * of disk, etc). - */ - mac_create_vnode(cred, dvp, tvp); - - error = mac_stdcreatevnode_ea(tvp); - if (error) - return (error); - - /* - * XXX: Eventually this will go away and all policies will - * directly manage their extended attributes. - */ - error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac); - if (error) - return (error); - - error = vn_extattr_set(tvp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); - if (error == 0) - tvp->v_vflag |= VV_CACHEDLABEL; - else { -#if 0 - /* - * In theory, we could have fall-back behavior here. - * It would probably be incorrect. - */ -#endif - return (error); - } - } - - return (0); + return (error); } void mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp) { - int error; ASSERT_VOP_LOCKED(vp, "mac_execve_transition"); - error = vn_refreshlabel(vp, old); - if (error) { - printf("mac_execve_transition: vn_refreshlabel returned %d\n", - error); - printf("mac_execve_transition: using old vnode label\n"); - } - MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label); } int mac_execve_will_transition(struct ucred *old, struct vnode *vp) { - int error, result; - - error = vn_refreshlabel(vp, old); - if (error) - return (error); + int result; result = 0; MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label); @@ -2040,10 +1860,6 @@ mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags); return (error); } @@ -2058,10 +1874,6 @@ mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label); return (error); } @@ -2076,10 +1888,6 @@ mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label); return (error); } @@ -2095,10 +1903,6 @@ mac_check_vnode_create(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap); return (error); } @@ -2115,13 +1919,6 @@ mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2138,10 +1935,6 @@ mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type); return (error); } @@ -2156,9 +1949,6 @@ mac_check_vnode_exec(struct ucred *cred, struct vnode *vp) if (!mac_enforce_process && !mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label); return (error); @@ -2174,10 +1964,6 @@ mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type); return (error); } @@ -2193,10 +1979,6 @@ mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2214,14 +1996,6 @@ mac_check_vnode_link(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2238,10 +2012,6 @@ mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp); return (error); } @@ -2256,10 +2026,6 @@ mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot); return (error); } @@ -2290,10 +2056,6 @@ mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot) if (!mac_enforce_fs || !mac_enforce_vm) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot); return (error); } @@ -2308,10 +2070,6 @@ mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode); return (error); } @@ -2327,10 +2085,6 @@ mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp, &vp->v_label); @@ -2348,10 +2102,6 @@ mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_read, active_cred, file_cred, vp, &vp->v_label); @@ -2368,10 +2118,6 @@ mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label); return (error); } @@ -2386,10 +2132,6 @@ mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label); return (error); } @@ -2402,10 +2144,6 @@ mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp, ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel"); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel); return (error); @@ -2423,13 +2161,6 @@ mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp, &vp->v_label, cnp); return (error); @@ -2447,14 +2178,6 @@ mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(dvp, cred); - if (error) - return (error); - if (vp != NULL) { - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - } MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp, vp != NULL ? &vp->v_label : NULL, samedir, cnp); return (error); @@ -2470,10 +2193,6 @@ mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label); return (error); } @@ -2489,10 +2208,6 @@ mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl); return (error); } @@ -2508,10 +2223,6 @@ mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label, attrnamespace, name, uio); return (error); @@ -2527,10 +2238,6 @@ mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags); return (error); } @@ -2545,10 +2252,6 @@ mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode); return (error); } @@ -2564,10 +2267,6 @@ mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid); return (error); } @@ -2583,10 +2282,6 @@ mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime, mtime); return (error); @@ -2603,10 +2298,6 @@ mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp, &vp->v_label); return (error); @@ -2622,10 +2313,6 @@ mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp) if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, cred); - if (error) - return (error); - MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label); return (error); } @@ -2641,10 +2328,6 @@ mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred, if (!mac_enforce_fs) return (0); - error = vn_refreshlabel(vp, active_cred); - if (error) - return (error); - MAC_CHECK(check_vnode_write, active_cred, file_cred, vp, &vp->v_label); @@ -3344,7 +3027,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3352,7 +3034,6 @@ mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr, } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_ifnet_label(&ifnet->if_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3382,7 +3063,6 @@ mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr, return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3444,16 +3124,6 @@ mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, &de->de_label); } -static int -mac_stdcreatevnode_ea(struct vnode *vp) -{ - int error; - - MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label); - - return (error); -} - void mac_create_devfs_directory(char *dirname, int dirnamelen, struct devfs_dirent *de) @@ -3463,29 +3133,6 @@ mac_create_devfs_directory(char *dirname, int dirnamelen, &de->de_label); } -/* - * When a new vnode is created, this call will initialize its label. - */ -void -mac_create_vnode(struct ucred *cred, struct vnode *parent, - struct vnode *child) -{ - int error; - - ASSERT_VOP_LOCKED(parent, "mac_create_vnode"); - ASSERT_VOP_LOCKED(child, "mac_create_vnode"); - - error = vn_refreshlabel(parent, cred); - if (error) { - printf("mac_create_vnode: vn_refreshlabel returned %d\n", - error); - printf("mac_create_vnode: using old vnode label\n"); - } - - MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child, - &child->v_label); -} - int mac_setsockopt_label_set(struct ucred *cred, struct socket *so, struct mac *mac) @@ -3499,7 +3146,6 @@ mac_setsockopt_label_set(struct ucred *cred, struct socket *so, return (error); buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3554,7 +3200,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3562,7 +3207,6 @@ mac_getsockopt_label_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_label(&so->so_label, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3586,7 +3230,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, return (error); elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3594,7 +3237,6 @@ mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so, } buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_socket_peer_label(&so->so_peerlabel, elements, buffer, mac->m_buflen, M_WAITOK); if (error == 0) @@ -3616,35 +3258,19 @@ vop_stdsetlabel_ea(struct vop_setlabel_args *ap) { struct vnode *vp = ap->a_vp; struct label *intlabel = ap->a_label; - struct oldmac extmac; int error; ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea"); - /* - * XXX: Eventually call out to EA check/set calls here. - * Be particularly careful to avoid race conditions, - * consistency problems, and stability problems when - * dealing with multiple EAs. In particular, we require - * the ability to write multiple EAs on the same file in - * a single transaction, which the current EA interface - * does not provide. - */ + if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) + return (EOPNOTSUPP); - error = mac_externalize_vnode_oldmac(intlabel, &extmac); - if (error) - return (error); - - error = vn_extattr_set(vp, IO_NODELOCKED, - FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, - sizeof(extmac), (char *)&extmac, curthread); + error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel); if (error) return (error); mac_relabel_vnode(ap->a_cred, vp, intlabel); - vp->v_vflag |= VV_CACHEDLABEL; - return (0); } @@ -3721,7 +3347,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3730,7 +3355,6 @@ __mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&tcred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3761,7 +3385,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3769,7 +3392,6 @@ __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - error = mac_externalize_cred_label(&td->td_ucred->cr_label, elements, buffer, mac.m_buflen, M_WAITOK); if (error == 0) @@ -3802,7 +3424,6 @@ __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -3880,7 +3501,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3888,7 +3508,6 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ error = fget(td, SCARG(uap, fd), &fp); if (error) @@ -3903,9 +3522,7 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap) mac_init_vnode_label(&intlabel); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - error = vn_refreshlabel(vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&vp->v_label, &intlabel); + mac_copy_vnode_label(&vp->v_label, &intlabel); VOP_UNLOCK(vp, 0, td); break; @@ -3974,7 +3591,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -3982,7 +3598,6 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -3991,12 +3606,9 @@ __mac_get_file(struct thread *td, struct __mac_get_file_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4034,7 +3646,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) return (error); elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL); if (error) { free(elements, M_MACTEMP); @@ -4042,7 +3653,6 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) } buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); - mtx_lock(&Giant); /* VFS */ NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p, td); @@ -4051,12 +3661,9 @@ __mac_get_link(struct thread *td, struct __mac_get_link_args *uap) goto out; mac_init_vnode_label(&intlabel); - error = vn_refreshlabel(nd.ni_vp, td->td_ucred); - if (error == 0) - mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); - if (error == 0) - error = mac_externalize_vnode_label(&intlabel, elements, - buffer, mac.m_buflen, M_WAITOK); + mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel); + error = mac_externalize_vnode_label(&intlabel, elements, buffer, + mac.m_buflen, M_WAITOK); NDFREE(&nd, 0); mac_destroy_vnode_label(&intlabel); @@ -4096,7 +3703,6 @@ __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4183,7 +3789,6 @@ __mac_set_file(struct thread *td, struct __mac_set_file_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); @@ -4240,7 +3845,6 @@ __mac_set_link(struct thread *td, struct __mac_set_link_args *uap) return (error); buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK); - error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL); if (error) { free(buffer, M_MACTEMP); diff --git a/sys/security/mac_biba/mac_biba.c b/sys/security/mac_biba/mac_biba.c index c30d39fdae57..9292a7306d67 100644 --- a/sys/security/mac_biba/mac_biba.c +++ b/sys/security/mac_biba/mac_biba.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,10 @@ SYSCTL_DECL(_security_mac); SYSCTL_NODE(_security_mac, OID_AUTO, biba, CTLFLAG_RW, 0, "TrustedBSD mac_biba policy controls"); +static int mac_biba_label_size = sizeof(struct mac_biba); +SYSCTL_INT(_security_mac_biba, OID_AUTO, label_size, CTLFLAG_RD, + &mac_biba_label_size, 0, "Size of struct mac_biba"); + static int mac_biba_enabled = 0; SYSCTL_INT(_security_mac_biba, OID_AUTO, enabled, CTLFLAG_RW, &mac_biba_enabled, 0, "Enforce MAC/Biba policy"); @@ -214,6 +219,19 @@ mac_biba_dominate_element(struct mac_biba_element *a, return (0); } +static int +mac_biba_subject_dominate_high(struct mac_biba *mac_biba) +{ + struct mac_biba_element *element; + + KASSERT((mac_biba->mb_single->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0, + ("mac_biba_single_in_range: mac_biba not single")); + element = &mac_biba->mb_single; + + return (element->mbe_type == MAC_BIBA_TYPE_EQUAL || + element->mbe_type == MAC_BIBA_TYPE_HIGH); +} + static int mac_biba_range_in_range(struct mac_biba *rangea, struct mac_biba *rangeb) { @@ -319,6 +337,15 @@ mac_biba_subject_equal_ok(struct mac_biba *mac_biba) return (EPERM); } +mac_biba_high_single(struct mac_biba *mac_biba) +{ + + KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0, + ("mac_biba_equal_single: mac_biba not single")); + + return (mac_biba->mb_single.mbe_type == MAC_BIBA_TYPE_HIGH); +} + static int mac_biba_valid(struct mac_biba *mac_biba) { @@ -619,23 +646,6 @@ mac_biba_externalize_label(struct label *label, char *element_name, return (0); } -static int -mac_biba_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - struct mac_biba *mac_biba; - - mac_biba = SLOT(label); - - if (mac_biba == NULL) { - printf("mac_biba_externalize_vnode_oldmac: NULL pointer\n"); - return (0); - } - - extmac->m_biba = *mac_biba; - - return (0); -} - static int mac_biba_parse_element(struct mac_biba_element *element, char *string) { @@ -846,18 +856,6 @@ mac_biba_create_devfs_vnode(struct devfs_dirent *devfs_dirent, mac_biba_copy_single(source, dest); } -static void -mac_biba_create_vnode(struct ucred *cred, struct vnode *parent, - struct label *parentlabel, struct vnode *child, struct label *childlabel) -{ - struct mac_biba *source, *dest; - - source = SLOT(&cred->cr_label); - dest = SLOT(childlabel); - - mac_biba_copy_single(source, dest); -} - static void mac_biba_create_mount(struct ucred *cred, struct mount *mp, struct label *mntlabel, struct label *fslabel) @@ -909,55 +907,116 @@ mac_biba_update_devfsdirent(struct devfs_dirent *devfs_dirent, } static void -mac_biba_update_procfsvnode(struct vnode *vp, struct label *vnodelabel, - struct ucred *cred) +mac_biba_associate_vnode_devfs(struct mount *mp, struct label *fslabel, + struct devfs_dirent *de, struct label *delabel, struct vnode *vp, + struct label *vlabel) { struct mac_biba *source, *dest; - source = SLOT(&cred->cr_label); - dest = SLOT(vnodelabel); + source = SLOT(delabel); + dest = SLOT(vlabel); - /* - * Only copy the single, not the range, since vnodes only have - * a single. - */ mac_biba_copy_single(source, dest); } static int -mac_biba_update_vnode_from_externalized(struct vnode *vp, - struct label *vnodelabel, struct oldmac *extmac) +mac_biba_associate_vnode_extattr(struct mount *mp, struct label *fslabel, + struct vnode *vp, struct label *vlabel) { - struct mac_biba *source, *dest; + struct mac_biba temp, *source, *dest; + size_t buflen; int error; - source = &extmac->m_biba; - dest = SLOT(vnodelabel); + source = SLOT(fslabel); + dest = SLOT(vlabel); - error = mac_biba_valid(source); - if (error) + buflen = sizeof(temp); + bzero(&temp, buflen); + + error = vn_extattr_get(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE, + MAC_BIBA_EXTATTR_NAME, &buflen, (char *) &temp, curthread); + if (error == ENOATTR || error == EOPNOTSUPP) { + /* Fall back to the fslabel. */ + mac_biba_copy_single(source, dest); + return (0); + } else if (error) return (error); - if ((source->mb_flags & MAC_BIBA_FLAGS_BOTH) != MAC_BIBA_FLAG_SINGLE) - return (EINVAL); - - mac_biba_copy_single(source, dest); + if (buflen != sizeof(temp)) { + printf("mac_biba_associate_vnode_extattr: bad size %d\n", + buflen); + return (EPERM); + } + if (mac_biba_valid(&temp) != 0) { + printf("mac_biba_associate_vnode_extattr: invalid\n"); + return (EPERM); + } + if ((temp.mb_flags & MAC_BIBA_FLAGS_BOTH) != MAC_BIBA_FLAG_SINGLE) { + printf("mac_biba_associate_vnode_extattr: not single\n"); + return (EPERM); + } + mac_biba_copy_single(&temp, dest); return (0); } static void -mac_biba_update_vnode_from_mount(struct vnode *vp, struct label *vnodelabel, - struct mount *mp, struct label *fslabel) +mac_biba_associate_vnode_singlelabel(struct mount *mp, + struct label *fslabel, struct vnode *vp, struct label *vlabel) { struct mac_biba *source, *dest; source = SLOT(fslabel); - dest = SLOT(vnodelabel); + dest = SLOT(vlabel); mac_biba_copy_single(source, dest); } +static int +mac_biba_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct label *fslabel, struct vnode *dvp, struct label *dlabel, + struct vnode *vp, struct label *vlabel, struct componentname *cnp) +{ + struct mac_biba *source, *dest, temp; + size_t buflen; + int error; + + buflen = sizeof(temp); + bzero(&temp, buflen); + + source = SLOT(&cred->cr_label); + dest = SLOT(vlabel); + mac_biba_copy_single(source, &temp); + + error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE, + MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread); + if (error == 0) + mac_biba_copy_single(source, dest); + return (error); +} + +static int +mac_biba_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *vlabel, struct label *intlabel) +{ + struct mac_biba *source, temp; + size_t buflen; + int error; + + buflen = sizeof(temp); + bzero(&temp, buflen); + + source = SLOT(intlabel); + if ((source->mb_flags & MAC_BIBA_FLAG_SINGLE) == 0) + return (0); + + mac_biba_copy_single(source, &temp); + + error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE, + MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread); + return (error); +} + /* * Labeling event operations: IPC object. */ @@ -2450,8 +2509,6 @@ static struct mac_policy_op_entry mac_biba_ops[] = (macop_t)mac_biba_externalize_label }, { MAC_EXTERNALIZE_VNODE_LABEL, (macop_t)mac_biba_externalize_label }, - { MAC_EXTERNALIZE_VNODE_OLDMAC, - (macop_t)mac_biba_externalize_vnode_oldmac }, { MAC_INTERNALIZE_CRED_LABEL, (macop_t)mac_biba_internalize_label }, { MAC_INTERNALIZE_IFNET_LABEL, @@ -2470,8 +2527,6 @@ static struct mac_policy_op_entry mac_biba_ops[] = (macop_t)mac_biba_create_devfs_symlink }, { MAC_CREATE_DEVFS_VNODE, (macop_t)mac_biba_create_devfs_vnode }, - { MAC_CREATE_VNODE, - (macop_t)mac_biba_create_vnode }, { MAC_CREATE_MOUNT, (macop_t)mac_biba_create_mount }, { MAC_CREATE_ROOT_MOUNT, @@ -2480,12 +2535,16 @@ static struct mac_policy_op_entry mac_biba_ops[] = (macop_t)mac_biba_relabel_vnode }, { MAC_UPDATE_DEVFSDIRENT, (macop_t)mac_biba_update_devfsdirent }, - { MAC_UPDATE_PROCFSVNODE, - (macop_t)mac_biba_update_procfsvnode }, - { MAC_UPDATE_VNODE_FROM_EXTERNALIZED, - (macop_t)mac_biba_update_vnode_from_externalized }, - { MAC_UPDATE_VNODE_FROM_MOUNT, - (macop_t)mac_biba_update_vnode_from_mount }, + { MAC_ASSOCIATE_VNODE_DEVFS, + (macop_t)mac_biba_associate_vnode_devfs }, + { MAC_ASSOCIATE_VNODE_EXTATTR, + (macop_t)mac_biba_associate_vnode_extattr }, + { MAC_ASSOCIATE_VNODE_SINGLELABEL, + (macop_t)mac_biba_associate_vnode_singlelabel }, + { MAC_CREATE_VNODE_EXTATTR, + (macop_t)mac_biba_create_vnode_extattr }, + { MAC_SETLABEL_VNODE_EXTATTR, + (macop_t)mac_biba_setlabel_vnode_extattr }, { MAC_CREATE_MBUF_FROM_SOCKET, (macop_t)mac_biba_create_mbuf_from_socket }, { MAC_CREATE_PIPE, diff --git a/sys/security/mac_mls/mac_mls.c b/sys/security/mac_mls/mac_mls.c index 02c1f7e92968..744e073a457b 100644 --- a/sys/security/mac_mls/mac_mls.c +++ b/sys/security/mac_mls/mac_mls.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,10 @@ SYSCTL_DECL(_security_mac); SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0, "TrustedBSD mac_mls policy controls"); +static int mac_mls_label_size = sizeof(struct mac_mls); +SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD, + &mac_mls_label_size, 0, "Size of struct mac_mls"); + static int mac_mls_enabled = 0; SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW, &mac_mls_enabled, 0, "Enforce MAC/MLS policy"); @@ -608,23 +613,6 @@ mac_mls_externalize_label(struct label *label, char *element_name, return (0); } -static int -mac_mls_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - struct mac_mls *mac_mls; - - mac_mls = SLOT(label); - - if (mac_mls == NULL) { - printf("mac_mls_externalize: NULL pointer\n"); - return (0); - } - - extmac->m_mls = *mac_mls; - - return (0); -} - static int mac_mls_parse_element(struct mac_mls_element *element, char *string) { @@ -838,18 +826,6 @@ mac_mls_create_devfs_vnode(struct devfs_dirent *devfs_dirent, mac_mls_copy_single(source, dest); } -static void -mac_mls_create_vnode(struct ucred *cred, struct vnode *parent, - struct label *parentlabel, struct vnode *child, struct label *childlabel) -{ - struct mac_mls *source, *dest; - - source = SLOT(&cred->cr_label); - dest = SLOT(childlabel); - - mac_mls_copy_single(source, dest); -} - static void mac_mls_create_mount(struct ucred *cred, struct mount *mp, struct label *mntlabel, struct label *fslabel) @@ -901,55 +877,116 @@ mac_mls_update_devfsdirent(struct devfs_dirent *devfs_dirent, } static void -mac_mls_update_procfsvnode(struct vnode *vp, struct label *vnodelabel, - struct ucred *cred) +mac_mls_associate_vnode_devfs(struct mount *mp, struct label *fslabel, + struct devfs_dirent *de, struct label *delabel, struct vnode *vp, + struct label *vlabel) { struct mac_mls *source, *dest; - source = SLOT(&cred->cr_label); - dest = SLOT(vnodelabel); + source = SLOT(delabel); + dest = SLOT(vlabel); - /* - * Only copy the single, not the range, since vnodes only have - * a single. - */ mac_mls_copy_single(source, dest); } static int -mac_mls_update_vnode_from_externalized(struct vnode *vp, - struct label *vnodelabel, struct oldmac *extmac) +mac_mls_associate_vnode_extattr(struct mount *mp, struct label *fslabel, + struct vnode *vp, struct label *vlabel) { - struct mac_mls *source, *dest; + struct mac_mls temp, *source, *dest; + size_t buflen; int error; - source = &extmac->m_mls; - dest = SLOT(vnodelabel); + source = SLOT(fslabel); + dest = SLOT(vlabel); - error = mac_mls_valid(source); - if (error) + buflen = sizeof(temp); + bzero(&temp, buflen); + + error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE, + MAC_MLS_EXTATTR_NAME, &buflen, (char *) &temp, curthread); + if (error == ENOATTR || error == EOPNOTSUPP) { + /* Fall back to the fslabel. */ + mac_mls_copy_single(source, dest); + return (0); + } else if (error) return (error); - if ((source->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE) - return (EINVAL); - - mac_mls_copy_single(source, dest); + if (buflen != sizeof(temp)) { + printf("mac_mls_associate_vnode_extattr: bad size %d\n", + buflen); + return (EPERM); + } + if (mac_mls_valid(&temp) != 0) { + printf("mac_mls_associate_vnode_extattr: invalid\n"); + return (EPERM); + } + if ((temp.mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE) { + printf("mac_mls_associated_vnode_extattr: not single\n"); + return (EPERM); + } + mac_mls_copy_single(&temp, dest); return (0); } static void -mac_mls_update_vnode_from_mount(struct vnode *vp, struct label *vnodelabel, - struct mount *mp, struct label *fslabel) +mac_mls_associate_vnode_singlelabel(struct mount *mp, + struct label *fslabel, struct vnode *vp, struct label *vlabel) { struct mac_mls *source, *dest; source = SLOT(fslabel); - dest = SLOT(vnodelabel); + dest = SLOT(vlabel); mac_mls_copy_single(source, dest); } +static int +mac_mls_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct label *fslabel, struct vnode *dvp, struct label *dlabel, + struct vnode *vp, struct label *vlabel, struct componentname *cnp) +{ + struct mac_mls *source, *dest, temp; + size_t buflen; + int error; + + buflen = sizeof(temp); + bzero(&temp, buflen); + + source = SLOT(&cred->cr_label); + dest = SLOT(vlabel); + mac_mls_copy_single(source, &temp); + + error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE, + MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread); + if (error == 0) + mac_mls_copy_single(source, dest); + return (error); +} + +static int +mac_mls_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *vlabel, struct label *intlabel) +{ + struct mac_mls *source, temp; + size_t buflen; + int error; + + buflen = sizeof(temp); + bzero(&temp, buflen); + + source = SLOT(intlabel); + if ((source->mm_flags & MAC_MLS_FLAG_SINGLE) == 0) + return (0); + + mac_mls_copy_single(source, &temp); + + error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE, + MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread); + return (error); +} + /* * Labeling event operations: IPC object. */ @@ -2405,8 +2442,6 @@ static struct mac_policy_op_entry mac_mls_ops[] = (macop_t)mac_mls_externalize_label }, { MAC_EXTERNALIZE_VNODE_LABEL, (macop_t)mac_mls_externalize_label }, - { MAC_EXTERNALIZE_VNODE_OLDMAC, - (macop_t)mac_mls_externalize_vnode_oldmac }, { MAC_INTERNALIZE_CRED_LABEL, (macop_t)mac_mls_internalize_label }, { MAC_INTERNALIZE_IFNET_LABEL, @@ -2425,8 +2460,6 @@ static struct mac_policy_op_entry mac_mls_ops[] = (macop_t)mac_mls_create_devfs_symlink }, { MAC_CREATE_DEVFS_VNODE, (macop_t)mac_mls_create_devfs_vnode }, - { MAC_CREATE_VNODE, - (macop_t)mac_mls_create_vnode }, { MAC_CREATE_MOUNT, (macop_t)mac_mls_create_mount }, { MAC_CREATE_ROOT_MOUNT, @@ -2435,12 +2468,16 @@ static struct mac_policy_op_entry mac_mls_ops[] = (macop_t)mac_mls_relabel_vnode }, { MAC_UPDATE_DEVFSDIRENT, (macop_t)mac_mls_update_devfsdirent }, - { MAC_UPDATE_PROCFSVNODE, - (macop_t)mac_mls_update_procfsvnode }, - { MAC_UPDATE_VNODE_FROM_EXTERNALIZED, - (macop_t)mac_mls_update_vnode_from_externalized }, - { MAC_UPDATE_VNODE_FROM_MOUNT, - (macop_t)mac_mls_update_vnode_from_mount }, + { MAC_ASSOCIATE_VNODE_DEVFS, + (macop_t)mac_mls_associate_vnode_devfs }, + { MAC_ASSOCIATE_VNODE_EXTATTR, + (macop_t)mac_mls_associate_vnode_extattr }, + { MAC_ASSOCIATE_VNODE_SINGLELABEL, + (macop_t)mac_mls_associate_vnode_singlelabel }, + { MAC_CREATE_VNODE_EXTATTR, + (macop_t)mac_mls_create_vnode_extattr }, + { MAC_SETLABEL_VNODE_EXTATTR, + (macop_t)mac_mls_setlabel_vnode_extattr }, { MAC_CREATE_MBUF_FROM_SOCKET, (macop_t)mac_mls_create_mbuf_from_socket }, { MAC_CREATE_PIPE, diff --git a/sys/security/mac_none/mac_none.c b/sys/security/mac_none/mac_none.c index 85eb896dac73..913fba2f162d 100644 --- a/sys/security/mac_none/mac_none.c +++ b/sys/security/mac_none/mac_none.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -135,13 +136,6 @@ mac_none_externalize_label(struct label *label, char *element_name, return (0); } -static int -mac_none_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - - return (0); -} - static int mac_none_internalize_label(struct label *label, char *element_name, char *element_data, int *claimed) @@ -154,6 +148,29 @@ mac_none_internalize_label(struct label *label, char *element_name, * Labeling event operations: file system objects, and things that look * a lot like file system objects. */ +static void +mac_none_associate_vnode_devfs(struct mount *mp, struct label *fslabel, + struct devfs_dirent *de, struct label *delabel, struct vnode *vp, + struct label *vlabel) +{ + +} + +static int +mac_none_associate_vnode_extattr(struct mount *mp, struct label *fslabel, + struct vnode *vp, struct label *vlabel) +{ + + return (0); +} + +static void +mac_none_associate_vnode_singlelabel(struct mount *mp, + struct label *fslabel, struct vnode *vp, struct label *vlabel) +{ + +} + static void mac_none_create_devfs_device(dev_t dev, struct devfs_dirent *devfs_dirent, struct label *label) @@ -182,12 +199,13 @@ mac_none_create_devfs_vnode(struct devfs_dirent *devfs_dirent, } -static void -mac_none_create_vnode(struct ucred *cred, struct vnode *parent, - struct label *parentlabel, struct vnode *child, - struct label *childlabel) +static int +mac_none_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct label *fslabel, struct vnode *dvp, struct label *dlabel, + struct vnode *vp, struct label *vlabel, struct componentname *cnp) { + return (0); } static void @@ -211,31 +229,17 @@ mac_none_relabel_vnode(struct ucred *cred, struct vnode *vp, } -static void -mac_none_update_devfsdirent(struct devfs_dirent *devfs_dirent, - struct label *direntlabel, struct vnode *vp, struct label *vnodelabel) -{ - -} - -static void -mac_none_update_procfsvnode(struct vnode *vp, struct label *vnodelabel, - struct ucred *cred) -{ - -} - static int -mac_none_update_vnode_from_externalized(struct vnode *vp, - struct label *vnodelabel, struct oldmac *extmac) +mac_none_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *vlabel, struct label *intlabel) { return (0); } static void -mac_none_update_vnode_from_mount(struct vnode *vp, struct label *vnodelabel, - struct mount *mp, struct label *fslabel) +mac_none_update_devfsdirent(struct devfs_dirent *devfs_dirent, + struct label *direntlabel, struct vnode *vp, struct label *vnodelabel) { } @@ -924,8 +928,6 @@ static struct mac_policy_op_entry mac_none_ops[] = (macop_t)mac_none_externalize_label }, { MAC_EXTERNALIZE_VNODE_LABEL, (macop_t)mac_none_externalize_label }, - { MAC_EXTERNALIZE_VNODE_OLDMAC, - (macop_t)mac_none_externalize_vnode_oldmac }, { MAC_INTERNALIZE_CRED_LABEL, (macop_t)mac_none_internalize_label }, { MAC_INTERNALIZE_IFNET_LABEL, @@ -936,6 +938,12 @@ static struct mac_policy_op_entry mac_none_ops[] = (macop_t)mac_none_internalize_label }, { MAC_INTERNALIZE_VNODE_LABEL, (macop_t)mac_none_internalize_label }, + { MAC_ASSOCIATE_VNODE_DEVFS, + (macop_t)mac_none_associate_vnode_devfs }, + { MAC_ASSOCIATE_VNODE_EXTATTR, + (macop_t)mac_none_associate_vnode_extattr }, + { MAC_ASSOCIATE_VNODE_SINGLELABEL, + (macop_t)mac_none_associate_vnode_singlelabel }, { MAC_CREATE_DEVFS_DEVICE, (macop_t)mac_none_create_devfs_device }, { MAC_CREATE_DEVFS_DIRECTORY, @@ -944,22 +952,18 @@ static struct mac_policy_op_entry mac_none_ops[] = (macop_t)mac_none_create_devfs_symlink }, { MAC_CREATE_DEVFS_VNODE, (macop_t)mac_none_create_devfs_vnode }, - { MAC_CREATE_VNODE, - (macop_t)mac_none_create_vnode }, + { MAC_CREATE_VNODE_EXTATTR, + (macop_t)mac_none_create_vnode_extattr }, { MAC_CREATE_MOUNT, (macop_t)mac_none_create_mount }, { MAC_CREATE_ROOT_MOUNT, (macop_t)mac_none_create_root_mount }, { MAC_RELABEL_VNODE, (macop_t)mac_none_relabel_vnode }, + { MAC_SETLABEL_VNODE_EXTATTR, + (macop_t)mac_none_setlabel_vnode_extattr }, { MAC_UPDATE_DEVFSDIRENT, (macop_t)mac_none_update_devfsdirent }, - { MAC_UPDATE_PROCFSVNODE, - (macop_t)mac_none_update_procfsvnode }, - { MAC_UPDATE_VNODE_FROM_EXTERNALIZED, - (macop_t)mac_none_update_vnode_from_externalized }, - { MAC_UPDATE_VNODE_FROM_MOUNT, - (macop_t)mac_none_update_vnode_from_mount }, { MAC_CREATE_MBUF_FROM_SOCKET, (macop_t)mac_none_create_mbuf_from_socket }, { MAC_CREATE_PIPE, diff --git a/sys/security/mac_stub/mac_stub.c b/sys/security/mac_stub/mac_stub.c index 85eb896dac73..913fba2f162d 100644 --- a/sys/security/mac_stub/mac_stub.c +++ b/sys/security/mac_stub/mac_stub.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -135,13 +136,6 @@ mac_none_externalize_label(struct label *label, char *element_name, return (0); } -static int -mac_none_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - - return (0); -} - static int mac_none_internalize_label(struct label *label, char *element_name, char *element_data, int *claimed) @@ -154,6 +148,29 @@ mac_none_internalize_label(struct label *label, char *element_name, * Labeling event operations: file system objects, and things that look * a lot like file system objects. */ +static void +mac_none_associate_vnode_devfs(struct mount *mp, struct label *fslabel, + struct devfs_dirent *de, struct label *delabel, struct vnode *vp, + struct label *vlabel) +{ + +} + +static int +mac_none_associate_vnode_extattr(struct mount *mp, struct label *fslabel, + struct vnode *vp, struct label *vlabel) +{ + + return (0); +} + +static void +mac_none_associate_vnode_singlelabel(struct mount *mp, + struct label *fslabel, struct vnode *vp, struct label *vlabel) +{ + +} + static void mac_none_create_devfs_device(dev_t dev, struct devfs_dirent *devfs_dirent, struct label *label) @@ -182,12 +199,13 @@ mac_none_create_devfs_vnode(struct devfs_dirent *devfs_dirent, } -static void -mac_none_create_vnode(struct ucred *cred, struct vnode *parent, - struct label *parentlabel, struct vnode *child, - struct label *childlabel) +static int +mac_none_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct label *fslabel, struct vnode *dvp, struct label *dlabel, + struct vnode *vp, struct label *vlabel, struct componentname *cnp) { + return (0); } static void @@ -211,31 +229,17 @@ mac_none_relabel_vnode(struct ucred *cred, struct vnode *vp, } -static void -mac_none_update_devfsdirent(struct devfs_dirent *devfs_dirent, - struct label *direntlabel, struct vnode *vp, struct label *vnodelabel) -{ - -} - -static void -mac_none_update_procfsvnode(struct vnode *vp, struct label *vnodelabel, - struct ucred *cred) -{ - -} - static int -mac_none_update_vnode_from_externalized(struct vnode *vp, - struct label *vnodelabel, struct oldmac *extmac) +mac_none_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *vlabel, struct label *intlabel) { return (0); } static void -mac_none_update_vnode_from_mount(struct vnode *vp, struct label *vnodelabel, - struct mount *mp, struct label *fslabel) +mac_none_update_devfsdirent(struct devfs_dirent *devfs_dirent, + struct label *direntlabel, struct vnode *vp, struct label *vnodelabel) { } @@ -924,8 +928,6 @@ static struct mac_policy_op_entry mac_none_ops[] = (macop_t)mac_none_externalize_label }, { MAC_EXTERNALIZE_VNODE_LABEL, (macop_t)mac_none_externalize_label }, - { MAC_EXTERNALIZE_VNODE_OLDMAC, - (macop_t)mac_none_externalize_vnode_oldmac }, { MAC_INTERNALIZE_CRED_LABEL, (macop_t)mac_none_internalize_label }, { MAC_INTERNALIZE_IFNET_LABEL, @@ -936,6 +938,12 @@ static struct mac_policy_op_entry mac_none_ops[] = (macop_t)mac_none_internalize_label }, { MAC_INTERNALIZE_VNODE_LABEL, (macop_t)mac_none_internalize_label }, + { MAC_ASSOCIATE_VNODE_DEVFS, + (macop_t)mac_none_associate_vnode_devfs }, + { MAC_ASSOCIATE_VNODE_EXTATTR, + (macop_t)mac_none_associate_vnode_extattr }, + { MAC_ASSOCIATE_VNODE_SINGLELABEL, + (macop_t)mac_none_associate_vnode_singlelabel }, { MAC_CREATE_DEVFS_DEVICE, (macop_t)mac_none_create_devfs_device }, { MAC_CREATE_DEVFS_DIRECTORY, @@ -944,22 +952,18 @@ static struct mac_policy_op_entry mac_none_ops[] = (macop_t)mac_none_create_devfs_symlink }, { MAC_CREATE_DEVFS_VNODE, (macop_t)mac_none_create_devfs_vnode }, - { MAC_CREATE_VNODE, - (macop_t)mac_none_create_vnode }, + { MAC_CREATE_VNODE_EXTATTR, + (macop_t)mac_none_create_vnode_extattr }, { MAC_CREATE_MOUNT, (macop_t)mac_none_create_mount }, { MAC_CREATE_ROOT_MOUNT, (macop_t)mac_none_create_root_mount }, { MAC_RELABEL_VNODE, (macop_t)mac_none_relabel_vnode }, + { MAC_SETLABEL_VNODE_EXTATTR, + (macop_t)mac_none_setlabel_vnode_extattr }, { MAC_UPDATE_DEVFSDIRENT, (macop_t)mac_none_update_devfsdirent }, - { MAC_UPDATE_PROCFSVNODE, - (macop_t)mac_none_update_procfsvnode }, - { MAC_UPDATE_VNODE_FROM_EXTERNALIZED, - (macop_t)mac_none_update_vnode_from_externalized }, - { MAC_UPDATE_VNODE_FROM_MOUNT, - (macop_t)mac_none_update_vnode_from_mount }, { MAC_CREATE_MBUF_FROM_SOCKET, (macop_t)mac_none_create_mbuf_from_socket }, { MAC_CREATE_PIPE, diff --git a/sys/security/mac_test/mac_test.c b/sys/security/mac_test/mac_test.c index b4b18a3ba81e..6a2cf76981da 100644 --- a/sys/security/mac_test/mac_test.c +++ b/sys/security/mac_test/mac_test.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -482,15 +483,6 @@ mac_test_externalize_label(struct label *label, char *element_name, return (0); } -static int -mac_test_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac) -{ - - atomic_add_int(&externalize_count, 1); - - return (0); -} - static int mac_test_internalize_label(struct label *label, struct mac *mac, char *element_name, char *element_data, int *claimed) @@ -505,6 +497,29 @@ mac_test_internalize_label(struct label *label, struct mac *mac, * Labeling event operations: file system objects, and things that look * a lot like file system objects. */ +static void +mac_test_associate_vnode_devfs(struct mount *mp, struct label *fslabel, + struct devfs_dirent *de, struct label *delabel, struct vnode *vp, + struct label *vlabel) +{ + +} + +static int +mac_test_associate_vnode_extattr(struct mount *mp, struct label *fslabel, + struct vnode *vp, struct label *vlabel) +{ + + return (0); +} + +static void +mac_test_associate_vnode_singlelabel(struct mount *mp, + struct label *fslabel, struct vnode *vp, struct label *vlabel) +{ + +} + static void mac_test_create_devfs_device(dev_t dev, struct devfs_dirent *devfs_dirent, struct label *label) @@ -533,11 +548,13 @@ mac_test_create_devfs_vnode(struct devfs_dirent *devfs_dirent, } -static void -mac_test_create_vnode(struct ucred *cred, struct vnode *parent, - struct label *parentlabel, struct vnode *child, struct label *childlabel) +static int +mac_test_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct label *fslabel, struct vnode *dvp, struct label *dlabel, + struct vnode *vp, struct label *vlabel, struct componentname *cnp) { + return (0); } static void @@ -561,31 +578,17 @@ mac_test_relabel_vnode(struct ucred *cred, struct vnode *vp, } -static void -mac_test_update_devfsdirent(struct devfs_dirent *devfs_dirent, - struct vnode *vp) -{ - -} - -static void -mac_test_update_procfsvnode(struct vnode *vp, struct label *vnodelabel, - struct ucred *cred) -{ - -} - static int -mac_test_update_vnode_from_externalized(struct vnode *vp, - struct label *vnodelabel, struct mac *extmac) +mac_test_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, + struct label *vlabel, struct label *intlabel) { return (0); } static void -mac_test_update_vnode_from_mount(struct vnode *vp, struct label *vnodelabel, - struct mount *mp, struct label *fslabel) +mac_test_update_devfsdirent(struct devfs_dirent *devfs_dirent, + struct label *direntlabel, struct vnode *vp, struct label *vnodelabel) { } @@ -1275,8 +1278,6 @@ static struct mac_policy_op_entry mac_test_ops[] = (macop_t)mac_test_externalize_label }, { MAC_EXTERNALIZE_VNODE_LABEL, (macop_t)mac_test_externalize_label }, - { MAC_EXTERNALIZE_VNODE_OLDMAC, - (macop_t)mac_test_externalize_vnode_oldmac }, { MAC_INTERNALIZE_CRED_LABEL, (macop_t)mac_test_internalize_label }, { MAC_INTERNALIZE_IFNET_LABEL, @@ -1287,6 +1288,12 @@ static struct mac_policy_op_entry mac_test_ops[] = (macop_t)mac_test_internalize_label }, { MAC_INTERNALIZE_VNODE_LABEL, (macop_t)mac_test_internalize_label }, + { MAC_ASSOCIATE_VNODE_DEVFS, + (macop_t)mac_test_associate_vnode_devfs }, + { MAC_ASSOCIATE_VNODE_EXTATTR, + (macop_t)mac_test_associate_vnode_extattr }, + { MAC_ASSOCIATE_VNODE_SINGLELABEL, + (macop_t)mac_test_associate_vnode_singlelabel }, { MAC_CREATE_DEVFS_DEVICE, (macop_t)mac_test_create_devfs_device }, { MAC_CREATE_DEVFS_DIRECTORY, @@ -1295,22 +1302,18 @@ static struct mac_policy_op_entry mac_test_ops[] = (macop_t)mac_test_create_devfs_symlink }, { MAC_CREATE_DEVFS_VNODE, (macop_t)mac_test_create_devfs_vnode }, - { MAC_CREATE_VNODE, - (macop_t)mac_test_create_vnode }, + { MAC_CREATE_VNODE_EXTATTR, + (macop_t)mac_test_create_vnode_extattr }, { MAC_CREATE_MOUNT, (macop_t)mac_test_create_mount }, { MAC_CREATE_ROOT_MOUNT, (macop_t)mac_test_create_root_mount }, { MAC_RELABEL_VNODE, (macop_t)mac_test_relabel_vnode }, + { MAC_SETLABEL_VNODE_EXTATTR, + (macop_t)mac_test_setlabel_vnode_extattr }, { MAC_UPDATE_DEVFSDIRENT, (macop_t)mac_test_update_devfsdirent }, - { MAC_UPDATE_PROCFSVNODE, - (macop_t)mac_test_update_procfsvnode }, - { MAC_UPDATE_VNODE_FROM_EXTERNALIZED, - (macop_t)mac_test_update_vnode_from_externalized }, - { MAC_UPDATE_VNODE_FROM_MOUNT, - (macop_t)mac_test_update_vnode_from_mount }, { MAC_CREATE_MBUF_FROM_SOCKET, (macop_t)mac_test_create_mbuf_from_socket }, { MAC_CREATE_PIPE, diff --git a/sys/sys/mac.h b/sys/sys/mac.h index bcf36e03b21f..cc9552b354bb 100644 --- a/sys/sys/mac.h +++ b/sys/sys/mac.h @@ -195,6 +195,8 @@ void mac_init_pipe(struct pipe *); int mac_init_mbuf(struct mbuf *m, int flag); void mac_init_mount(struct mount *); void mac_init_vnode(struct vnode *); +void mac_init_vnode_label(struct label *); +void mac_copy_vnode_label(struct label *, struct label *label); void mac_destroy_bpfdesc(struct bpf_d *); void mac_destroy_cred(struct ucred *); void mac_destroy_devfsdirent(struct devfs_dirent *); @@ -205,26 +207,29 @@ void mac_destroy_pipe(struct pipe *); void mac_destroy_mbuf(struct mbuf *); void mac_destroy_mount(struct mount *); void mac_destroy_vnode(struct vnode *); +void mac_destroy_vnode_label(struct label *); /* * Labeling event operations: file system objects, and things that * look a lot like file system objects. */ +void mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de, + struct vnode *vp); +int mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp); +void mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp); void mac_create_devfs_device(dev_t dev, struct devfs_dirent *de); void mac_create_devfs_directory(char *dirname, int dirnamelen, struct devfs_dirent *de); void mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd, struct devfs_dirent *de); void mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp); -void mac_create_vnode(struct ucred *cred, struct vnode *parent, - struct vnode *child); +int mac_create_vnode_extattr(struct ucred *cred, struct mount *mp, + struct vnode *dvp, struct vnode *vp, struct componentname *cnp); void mac_create_mount(struct ucred *cred, struct mount *mp); void mac_create_root_mount(struct ucred *cred, struct mount *mp); void mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel); void mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp); -void mac_update_procfsvnode(struct vnode *vp, struct ucred *cred); -void mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp); /* * Labeling event operations: IPC objects. @@ -362,9 +367,6 @@ int mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, * Calls to help various file systems implement labeling functionality * using their existing EA implementation. */ -int vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, - struct ucred *cred); -int vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap); int vop_stdsetlabel_ea(struct vop_setlabel_args *ap); #endif /* _KERNEL */ diff --git a/sys/sys/mac_policy.h b/sys/sys/mac_policy.h index aabc95e3e745..46c4c1bc558f 100644 --- a/sys/sys/mac_policy.h +++ b/sys/sys/mac_policy.h @@ -118,8 +118,6 @@ struct mac_policy_ops { int (*mpo_externalize_vnode_label)(struct label *label, char *element_name, char *buffer, size_t buflen, size_t *len, int *claimed); - int (*mpo_externalize_vnode_oldmac)(struct label *label, - struct oldmac *extmac); int (*mpo_internalize_cred_label)(struct label *label, char *element_name, char *element_data, int *claimed); int (*mpo_internalize_ifnet_label)(struct label *label, @@ -135,6 +133,16 @@ struct mac_policy_ops { * Labeling event operations: file system objects, and things that * look a lot like file system objects. */ + void (*mpo_associate_vnode_devfs)(struct mount *mp, + struct label *fslabel, struct devfs_dirent *de, + struct label *delabel, struct vnode *vp, + struct label *vlabel); + int (*mpo_associate_vnode_extattr)(struct mount *mp, + struct label *fslabel, struct vnode *vp, + struct label *vlabel); + void (*mpo_associate_vnode_singlelabel)(struct mount *mp, + struct label *fslabel, struct vnode *vp, + struct label *vlabel); void (*mpo_create_devfs_device)(dev_t dev, struct devfs_dirent *de, struct label *label); void (*mpo_create_devfs_directory)(char *dirname, int dirnamelen, @@ -145,30 +153,23 @@ struct mac_policy_ops { void (*mpo_create_devfs_vnode)(struct devfs_dirent *de, struct label *direntlabel, struct vnode *vp, struct label *vnodelabel); - void (*mpo_create_vnode)(struct ucred *cred, struct vnode *parent, - struct label *parentlabel, struct vnode *child, - struct label *childlabel); + int (*mpo_create_vnode_extattr)(struct ucred *cred, + struct mount *mp, struct label *fslabel, + struct vnode *dvp, struct label *dlabel, + struct vnode *vp, struct label *vlabel, + struct componentname *cnp); void (*mpo_create_mount)(struct ucred *cred, struct mount *mp, struct label *mntlabel, struct label *fslabel); void (*mpo_create_root_mount)(struct ucred *cred, struct mount *mp, struct label *mountlabel, struct label *fslabel); void (*mpo_relabel_vnode)(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *label); - int (*mpo_stdcreatevnode_ea)(struct vnode *vp, - struct label *vnodelabel); + int (*mpo_setlabel_vnode_extattr)(struct ucred *cred, + struct vnode *vp, struct label *vlabel, + struct label *intlabel); void (*mpo_update_devfsdirent)(struct devfs_dirent *devfs_dirent, struct label *direntlabel, struct vnode *vp, struct label *vnodelabel); - void (*mpo_update_procfsvnode)(struct vnode *vp, - struct label *vnodelabel, struct ucred *cred); - int (*mpo_update_vnode_from_extattr)(struct vnode *vp, - struct label *vnodelabel, struct mount *mp, - struct label *fslabel); - int (*mpo_update_vnode_from_externalized)(struct vnode *vp, - struct label *vnodelabel, struct oldmac *extmac); - void (*mpo_update_vnode_from_mount)(struct vnode *vp, - struct label *vnodelabel, struct mount *mp, - struct label *fslabel); /* * Labeling event operations: IPC objects. @@ -431,7 +432,6 @@ enum mac_op_constant { MAC_EXTERNALIZE_SOCKET_LABEL, MAC_EXTERNALIZE_SOCKET_PEER_LABEL, MAC_EXTERNALIZE_VNODE_LABEL, - MAC_EXTERNALIZE_VNODE_OLDMAC, MAC_INTERNALIZE_CRED_LABEL, MAC_INTERNALIZE_IFNET_LABEL, MAC_INTERNALIZE_PIPE_LABEL, @@ -441,16 +441,15 @@ enum mac_op_constant { MAC_CREATE_DEVFS_DIRECTORY, MAC_CREATE_DEVFS_SYMLINK, MAC_CREATE_DEVFS_VNODE, - MAC_CREATE_VNODE, MAC_CREATE_MOUNT, MAC_CREATE_ROOT_MOUNT, MAC_RELABEL_VNODE, - MAC_STDCREATEVNODE_EA, MAC_UPDATE_DEVFSDIRENT, - MAC_UPDATE_PROCFSVNODE, - MAC_UPDATE_VNODE_FROM_EXTATTR, - MAC_UPDATE_VNODE_FROM_EXTERNALIZED, - MAC_UPDATE_VNODE_FROM_MOUNT, + MAC_ASSOCIATE_VNODE_DEVFS, + MAC_ASSOCIATE_VNODE_EXTATTR, + MAC_ASSOCIATE_VNODE_SINGLELABEL, + MAC_CREATE_VNODE_EXTATTR, + MAC_SETLABEL_VNODE_EXTATTR, MAC_CREATE_MBUF_FROM_SOCKET, MAC_CREATE_PIPE, MAC_CREATE_SOCKET, diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index b80cd1c4e627..91d396bf5798 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -1337,6 +1338,23 @@ ffs_vget(mp, ino, flags, vpp) ip->i_gid = ip->i_din1->di_ogid; /* XXX */ } /* XXX */ +#ifdef MAC + if ((mp->mnt_flag & MNT_MULTILABEL) && ip->i_mode) { + /* + * If this vnode is already allocated, and we're running + * multi-label, attempt to perform a label association + * from the extended attributes on the inode. + */ + error = mac_associate_vnode_extattr(mp, vp); + if (error) { + /* ufs_inactive will release ip->i_devvp ref. */ + vput(vp); + *vpp = NULL; + return (error); + } + } +#endif + *vpp = vp; return (0); } diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index ba6edd2f26f2..f8867e1774c1 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -1523,9 +1523,12 @@ ufs_mkdir(ap) if (error) goto bad; #ifdef MAC - error = vop_stdcreatevnode_ea(dvp, tvp, cnp->cn_cred); - if (error) - goto bad; + if (dvp->v_mount->mnt_flag & MNT_MULTILABEL) { + error = mac_create_vnode_extattr(cnp->cn_cred, dvp->v_mount, + dvp, tvp, cnp); + if (error) + goto bad; + } #endif #ifdef UFS_ACL if (acl != NULL) { @@ -2459,9 +2462,12 @@ ufs_makeinode(mode, dvp, vpp, cnp) if (error) goto bad; #ifdef MAC - error = vop_stdcreatevnode_ea(dvp, tvp, cnp->cn_cred); - if (error) - goto bad; + if (dvp->v_mount->mnt_flag & MNT_MULTILABEL) { + error = mac_create_vnode_extattr(cnp->cn_cred, dvp->v_mount, + dvp, tvp, cnp); + if (error) + goto bad; + } #endif #ifdef UFS_ACL if (acl != NULL) { @@ -2649,9 +2655,6 @@ static struct vnodeopv_entry_desc ufs_vnodeop_entries[] = { { &vop_readdir_desc, (vop_t *) ufs_readdir }, { &vop_readlink_desc, (vop_t *) ufs_readlink }, { &vop_reclaim_desc, (vop_t *) ufs_reclaim }, -#ifdef MAC - { &vop_refreshlabel_desc, (vop_t *) vop_stdrefreshlabel_ea }, -#endif { &vop_remove_desc, (vop_t *) ufs_remove }, { &vop_rename_desc, (vop_t *) ufs_rename }, { &vop_rmdir_desc, (vop_t *) ufs_rmdir }, @@ -2690,9 +2693,6 @@ static struct vnodeopv_entry_desc ufs_specop_entries[] = { { &vop_print_desc, (vop_t *) ufs_print }, { &vop_read_desc, (vop_t *) ufsspec_read }, { &vop_reclaim_desc, (vop_t *) ufs_reclaim }, -#ifdef MAC - { &vop_refreshlabel_desc, (vop_t *) vop_stdrefreshlabel_ea }, -#endif { &vop_setattr_desc, (vop_t *) ufs_setattr }, #ifdef MAC { &vop_setlabel_desc, (vop_t *) vop_stdsetlabel_ea }, @@ -2727,9 +2727,6 @@ static struct vnodeopv_entry_desc ufs_fifoop_entries[] = { { &vop_print_desc, (vop_t *) ufs_print }, { &vop_read_desc, (vop_t *) ufsfifo_read }, { &vop_reclaim_desc, (vop_t *) ufs_reclaim }, -#ifdef MAC - { &vop_refreshlabel_desc, (vop_t *) vop_stdrefreshlabel_ea }, -#endif { &vop_setattr_desc, (vop_t *) ufs_setattr }, #ifdef MAC { &vop_setlabel_desc, (vop_t *) vop_stdsetlabel_ea },