X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/3903760236c30e3b5ace7a4eefac3a269d68957c..c3c9b80d004dbbfdf763edeb97968c6997e3b45b:/security/mac_vfs.c?ds=sidebyside diff --git a/security/mac_vfs.c b/security/mac_vfs.c index 7d7d6ea9a..ba95c90cb 100644 --- a/security/mac_vfs.c +++ b/security/mac_vfs.c @@ -2,7 +2,7 @@ * Copyright (c) 2007-2016 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,7 +22,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /*- @@ -63,6 +63,7 @@ */ #include +#include #include #include @@ -80,6 +81,8 @@ #include #include #include +#include + #include #include @@ -87,7 +90,33 @@ #include /* convert {R,W,X}_OK values to V{READ,WRITE,EXEC} */ -#define ACCESS_MODE_TO_VNODE_MASK(m) (m << 6) +#define ACCESS_MODE_TO_VNODE_MASK(m) (m << 6) + + +/* + * Optional tracing of policy operations. Define VFS_TRACE_POLICY_OPS to trace the operations. + * + * Along with DBG_FSYSTEM and DBG_VFS, dcode in the macros below is used to construct + * KDBG_EVENTID(DBG_FSYSTEM, DBG_VFS, dcode) global event id, see bsd/sys/kdebug.h. + * Note that dcode is multiplied by 4 and ORed as part of the construction. See bsd/kern/trace_codes + * for list of system-wide {global event id, name} pairs. Currently DBG_VFS event ids are in range + * [0x3130000, 0x3130174]. + */ + +//#define VFS_TRACE_POLICY_OPS + +#ifdef VFS_TRACE_POLICY_OPS +#define DBG_VFS_CODE(dcode) FSDBG_CODE(DBG_VFS, dcode) +#define VFS_KERNEL_DEBUG_START0(dcode) KERNEL_DEBUG_CONSTANT(DBG_VFS_CODE(dcode) | DBG_FUNC_START, 0, 0, 0, 0, 0) +#define VFS_KERNEL_DEBUG_END0(dcode) KERNEL_DEBUG_CONSTANT(DBG_VFS_CODE(dcode) | DBG_FUNC_END, 0, 0, 0, 0, 0) +#define VFS_KERNEL_DEBUG_START1(dcode, darg) KERNEL_DEBUG_CONSTANT(DBG_VFS_CODE(dcode) | DBG_FUNC_START, darg, 0, 0, 0, 0) +#define VFS_KERNEL_DEBUG_END1(dcode, darg) KERNEL_DEBUG_CONSTANT(DBG_VFS_CODE(dcode) | DBG_FUNC_END, darg, 0, 0, 0, 0) +#else +#define VFS_KERNEL_DEBUG_START0(dcode) do {} while (0) +#define VFS_KERNEL_DEBUG_END0(dcode) do {} while (0) +#define VFS_KERNEL_DEBUG_START1(dcode, darg) do {} while (0) +#define VFS_KERNEL_DEBUG_END1(dcode, darg) do {} while (0) +#endif static struct label * mac_devfsdirent_label_alloc(void) @@ -95,16 +124,18 @@ mac_devfsdirent_label_alloc(void) struct label *label; label = mac_labelzone_alloc(MAC_WAITOK); - if (label == NULL) - return (NULL); + if (label == NULL) { + return NULL; + } + VFS_KERNEL_DEBUG_START0(0); MAC_PERFORM(devfs_label_init, label); - return (label); + VFS_KERNEL_DEBUG_END0(0); + return label; } void mac_devfs_label_init(struct devnode *de) { - de->dn_label = mac_devfsdirent_label_alloc(); } @@ -114,16 +145,18 @@ mac_mount_label_alloc(void) struct label *label; label = mac_labelzone_alloc(MAC_WAITOK); - if (label == NULL) - return (NULL); + if (label == NULL) { + return NULL; + } + VFS_KERNEL_DEBUG_START0(1); MAC_PERFORM(mount_label_init, label); - return (label); + VFS_KERNEL_DEBUG_END0(1); + return label; } void mac_mount_label_init(struct mount *mp) { - mp->mnt_mntlabel = mac_mount_label_alloc(); } @@ -133,10 +166,14 @@ mac_vnode_label_alloc(void) struct label *label; label = mac_labelzone_alloc(MAC_WAITOK); - if (label == NULL) - return (NULL); + if (label == NULL) { + return NULL; + } + VFS_KERNEL_DEBUG_START0(2); MAC_PERFORM(vnode_label_init, label); - return (label); + VFS_KERNEL_DEBUG_END0(2); + OSIncrementAtomic(&mac_vnode_label_count); + return label; } void @@ -148,25 +185,47 @@ mac_vnode_label_init(vnode_t vp) int mac_vnode_label_init_needed(vnode_t vp) { - return (mac_label_vnodes != 0 && vp->v_label == NULL); +#if CONFIG_MACF_LAZY_VNODE_LABELS + (void)vp; + return false; +#else + return mac_label_vnodes != 0 && vp->v_label == NULL; +#endif +} + +struct label * +mac_vnode_label_allocate(vnode_t vp) +{ + if (mac_vnode_label_init_needed(vp)) { + vp->v_label = mac_vnode_label_alloc(); + } + return vp->v_label; } -/* +/* * vnode labels are allocated at the same time as vnodes, but vnodes are never * freed. Instead, we want to remove any sensitive information before putting * them on the free list for reuse. -*/ + */ void mac_vnode_label_recycle(vnode_t vp) { - MAC_PERFORM(vnode_label_recycle, vp->v_label); +#if CONFIG_MACF_LAZY_VNODE_LABELS + if (vp->v_label) { + mac_vnode_label_destroy(vp); + vp->v_label = NULL; + vp->v_lflag &= ~VL_LABELED; + } +#endif } static void mac_devfs_label_free(struct label *label) { + VFS_KERNEL_DEBUG_START1(3, label); MAC_PERFORM(devfs_label_destroy, label); + VFS_KERNEL_DEBUG_END1(3, label); mac_labelzone_free(label); } @@ -182,8 +241,9 @@ mac_devfs_label_destroy(struct devnode *de) static void mac_mount_label_free(struct label *label) { - + VFS_KERNEL_DEBUG_START1(4, label); MAC_PERFORM(mount_label_destroy, label); + VFS_KERNEL_DEBUG_END1(4, label); mac_labelzone_free(label); } @@ -199,11 +259,15 @@ mac_mount_label_destroy(struct mount *mp) void mac_vnode_label_free(struct label *label) { - MAC_PERFORM(vnode_label_destroy, label); - mac_labelzone_free(label); + if (label != NULL) { + VFS_KERNEL_DEBUG_START1(5, label); + MAC_PERFORM(vnode_label_destroy, label); + VFS_KERNEL_DEBUG_END1(5, label); + mac_labelzone_free(label); + OSDecrementAtomic(&mac_vnode_label_count); + } } -#ifndef __APPLE__ void mac_vnode_label_destroy(struct vnode *vp) { @@ -212,16 +276,17 @@ mac_vnode_label_destroy(struct vnode *vp) vp->v_label = NULL; } } -#endif void mac_vnode_label_copy(struct label *src, struct label *dest) { + VFS_KERNEL_DEBUG_START1(6, src); if (src == NULL) { MAC_PERFORM(vnode_label_init, dest); } else { MAC_PERFORM(vnode_label_copy, src, dest); } + VFS_KERNEL_DEBUG_END1(6, src); } int @@ -233,7 +298,7 @@ mac_vnode_label_externalize_audit(struct vnode *vp, struct mac *mac) error = MAC_EXTERNALIZE_AUDIT(vnode, vp->v_label, mac->m_string, mac->m_buflen); - return (error); + return error; } int @@ -244,7 +309,7 @@ mac_vnode_label_externalize(struct label *label, char *elements, error = MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen); - return (error); + return error; } int @@ -254,7 +319,7 @@ mac_vnode_label_internalize(struct label *label, char *string) error = MAC_INTERNALIZE(vnode, label, string); - return (error); + return error; } int @@ -264,7 +329,7 @@ mac_mount_label_internalize(struct label *label, char *string) error = MAC_INTERNALIZE(mount, label, string); - return (error); + return error; } int @@ -275,7 +340,7 @@ mac_mount_label_externalize(struct label *label, char *elements, error = MAC_EXTERNALIZE(mount, label, elements, outbuf, outbuflen); - return (error); + return error; } void @@ -283,11 +348,14 @@ mac_devfs_label_copy(struct label *src, struct label *dest) { #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_device_enforce) + if (!mac_device_enforce) { return; + } #endif + VFS_KERNEL_DEBUG_START1(7, src); MAC_PERFORM(devfs_label_copy, src, dest); + VFS_KERNEL_DEBUG_END1(7, src); } void @@ -296,12 +364,15 @@ mac_devfs_label_update(struct mount *mp, struct devnode *de, { #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_device_enforce) + if (!mac_device_enforce) { return; + } #endif + VFS_KERNEL_DEBUG_START1(8, vp); MAC_PERFORM(devfs_label_update, mp, de, de->dn_label, vp, vp->v_label); + VFS_KERNEL_DEBUG_END1(8, vp); } int @@ -313,8 +384,9 @@ mac_vnode_label_associate(struct mount *mp, struct vnode *vp, vfs_context_t ctx) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) - return (error); + if (!mac_vnode_enforce) { + return error; + } #endif /* XXX: should not inspect v_tag in kernel! */ @@ -332,7 +404,7 @@ mac_vnode_label_associate(struct mount *mp, struct vnode *vp, vfs_context_t ctx) break; } - return (error); + return error; } void @@ -341,14 +413,17 @@ mac_vnode_label_associate_devfs(struct mount *mp, struct devnode *de, { #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_device_enforce) + if (!mac_device_enforce) { return; + } #endif + VFS_KERNEL_DEBUG_START1(9, vp); MAC_PERFORM(vnode_label_associate_devfs, mp, mp ? mp->mnt_mntlabel : NULL, de, de->dn_label, vp, vp->v_label); + VFS_KERNEL_DEBUG_END1(9, vp); } int @@ -356,10 +431,12 @@ mac_vnode_label_associate_extattr(struct mount *mp, struct vnode *vp) { int error; + VFS_KERNEL_DEBUG_START1(10, vp); MAC_CHECK(vnode_label_associate_extattr, mp, mp->mnt_mntlabel, vp, vp->v_label); + VFS_KERNEL_DEBUG_END1(10, vp); - return (error); + return error; } void @@ -367,14 +444,18 @@ mac_vnode_label_associate_singlelabel(struct mount *mp, struct vnode *vp) { #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_label_vnodes) + if (!mac_label_vnodes) { return; + } + VFS_KERNEL_DEBUG_START1(11, vp); MAC_PERFORM(vnode_label_associate_singlelabel, mp, mp ? mp->mnt_mntlabel : NULL, vp, vp->v_label); + VFS_KERNEL_DEBUG_END1(11, vp); } int @@ -386,17 +467,20 @@ mac_vnode_notify_create(vfs_context_t ctx, struct mount *mp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) - return (0); + if (!mac_vnode_enforce) { + return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return (0); - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(12, vp); MAC_CHECK(vnode_notify_create, cred, mp, mp->mnt_mntlabel, dvp, dvp->v_label, vp, vp->v_label, cnp); + VFS_KERNEL_DEBUG_END1(12, vp); - return (error); + return error; } void @@ -407,15 +491,18 @@ mac_vnode_notify_rename(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return; + } + VFS_KERNEL_DEBUG_START1(13, vp); MAC_PERFORM(vnode_notify_rename, cred, vp, vp->v_label, dvp, dvp->v_label, cnp); + VFS_KERNEL_DEBUG_END1(13, vp); } void @@ -425,32 +512,38 @@ mac_vnode_notify_open(vfs_context_t ctx, struct vnode *vp, int acc_flags) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return; + } + VFS_KERNEL_DEBUG_START1(14, vp); MAC_PERFORM(vnode_notify_open, cred, vp, vp->v_label, acc_flags); + VFS_KERNEL_DEBUG_END1(14, vp); } void mac_vnode_notify_link(vfs_context_t ctx, struct vnode *vp, - struct vnode *dvp, struct componentname *cnp) + struct vnode *dvp, struct componentname *cnp) { kauth_cred_t cred; #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return; + } + VFS_KERNEL_DEBUG_START1(15, vp); MAC_PERFORM(vnode_notify_link, cred, dvp, dvp->v_label, vp, vp->v_label, cnp); + VFS_KERNEL_DEBUG_END1(15, vp); } void @@ -460,14 +553,17 @@ mac_vnode_notify_deleteextattr(vfs_context_t ctx, struct vnode *vp, const char * #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return; + } + VFS_KERNEL_DEBUG_START1(16, vp); MAC_PERFORM(vnode_notify_deleteextattr, cred, vp, vp->v_label, name); + VFS_KERNEL_DEBUG_END1(16, vp); } void @@ -477,14 +573,17 @@ mac_vnode_notify_setacl(vfs_context_t ctx, struct vnode *vp, struct kauth_acl *a #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return; + } + VFS_KERNEL_DEBUG_START1(17, vp); MAC_PERFORM(vnode_notify_setacl, cred, vp, vp->v_label, acl); + VFS_KERNEL_DEBUG_END1(17, vp); } void @@ -494,14 +593,17 @@ mac_vnode_notify_setattrlist(vfs_context_t ctx, struct vnode *vp, struct attrlis #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return; + } + VFS_KERNEL_DEBUG_START1(18, vp); MAC_PERFORM(vnode_notify_setattrlist, cred, vp, vp->v_label, alist); + VFS_KERNEL_DEBUG_END1(18, vp); } void @@ -511,14 +613,17 @@ mac_vnode_notify_setextattr(vfs_context_t ctx, struct vnode *vp, const char *nam #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return; + } + VFS_KERNEL_DEBUG_START1(19, vp); MAC_PERFORM(vnode_notify_setextattr, cred, vp, vp->v_label, name, uio); + VFS_KERNEL_DEBUG_END1(19, vp); } void @@ -528,14 +633,17 @@ mac_vnode_notify_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return; + } + VFS_KERNEL_DEBUG_START1(20, vp); MAC_PERFORM(vnode_notify_setflags, cred, vp, vp->v_label, flags); + VFS_KERNEL_DEBUG_END1(20, vp); } void @@ -545,14 +653,17 @@ mac_vnode_notify_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return; + } + VFS_KERNEL_DEBUG_START1(21, vp); MAC_PERFORM(vnode_notify_setmode, cred, vp, vp->v_label, mode); + VFS_KERNEL_DEBUG_END1(21, vp); } void @@ -562,14 +673,17 @@ mac_vnode_notify_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid, gid_t #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return; + } + VFS_KERNEL_DEBUG_START1(22, vp); MAC_PERFORM(vnode_notify_setowner, cred, vp, vp->v_label, uid, gid); + VFS_KERNEL_DEBUG_END1(22, vp); } void @@ -579,14 +693,17 @@ mac_vnode_notify_setutimes(vfs_context_t ctx, struct vnode *vp, struct timespec #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return; + } + VFS_KERNEL_DEBUG_START1(23, vp); MAC_PERFORM(vnode_notify_setutimes, cred, vp, vp->v_label, atime, mtime); + VFS_KERNEL_DEBUG_END1(23, vp); } void @@ -596,14 +713,17 @@ mac_vnode_notify_truncate(vfs_context_t ctx, kauth_cred_t file_cred, struct vnod #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return; + } + VFS_KERNEL_DEBUG_START1(24, vp); MAC_PERFORM(vnode_notify_truncate, cred, file_cred, vp, vp->v_label); + VFS_KERNEL_DEBUG_END1(24, vp); } /* @@ -619,16 +739,21 @@ mac_vnode_label_update_extattr(struct mount *mp, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return; + } #endif - if (!mac_label_vnodes) + if (!mac_label_vnodes) { return; + } + VFS_KERNEL_DEBUG_START1(25, vp); MAC_PERFORM(vnode_label_update_extattr, mp, mp->mnt_mntlabel, vp, - vp->v_label, name); - if (error == 0) + vp->v_label, name); + VFS_KERNEL_DEBUG_END1(25, vp); + if (error == 0) { return; + } vnode_lock(vp); vnode_relabel(vp); @@ -645,23 +770,29 @@ mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_label_vnodes || - !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + if (!mac_label_vnodes) { return 0; + } cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(26, vp); MAC_CHECK(vnode_label_store, cred, vp, vp->v_label, intlabel); + VFS_KERNEL_DEBUG_END1(26, vp); - return (error); + return error; } void mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp, off_t offset, - struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execl, u_int *csflags, - void *macextensions, int *disjoint, int *labelupdateerror) + struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execl, u_int *csflags, + void *macextensions, int *disjoint, int *labelupdateerror) { kauth_cred_t cred; *disjoint = 0; @@ -670,8 +801,9 @@ mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode * #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_proc_enforce || !mac_vnode_enforce) + if (!mac_proc_enforce || !mac_vnode_enforce) { return; + } #endif /* mark the new cred to indicate "matching" includes the label */ @@ -684,66 +816,74 @@ mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode * * calling exec_spawnattr_getmacpolicyinfo() and before passing the * spawnattrlen as an argument to the hook. */ + VFS_KERNEL_DEBUG_START1(27, vp); { struct mac_policy_conf *mpc; u_int i; error = 0; - for (i = 0; i< mac_policy_list.staticmax; i++) { + for (i = 0; i < mac_policy_list.staticmax; i++) { mpc = mac_policy_list.entries[i].mpc; - if (mpc == NULL) + if (mpc == NULL) { continue; + } mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve; - if (hook == NULL) + if (hook == NULL) { continue; + } size_t spawnattrlen = 0; void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen); error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp, - vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint), - error); + vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint), + error); } - if (mac_policy_list_conditional_busy() != 0) { + if (mac_policy_list_conditional_busy() != 0) { for (; i <= mac_policy_list.maxindex; i++) { mpc = mac_policy_list.entries[i].mpc; - if (mpc == NULL) + if (mpc == NULL) { continue; + } mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve; - if (hook == NULL) + if (hook == NULL) { continue; + } size_t spawnattrlen = 0; void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen); error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp, - vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint), - error); + vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint), + error); } mac_policy_list_unbusy(); } } *labelupdateerror = error; + VFS_KERNEL_DEBUG_END1(27, vp); } int mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp, off_t offset, - struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execlabel, - struct proc *p, void *macextensions) + struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execlabel, + struct proc *p, void *macextensions) { kauth_cred_t cred; int result = 0; #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_proc_enforce || !mac_vnode_enforce) + if (!mac_proc_enforce || !mac_vnode_enforce) { return result; + } #endif cred = vfs_context_ucred(ctx); + VFS_KERNEL_DEBUG_START1(28, vp); /* * NB: Cannot use MAC_BOOLEAN macro because we need a sequence point after * calling exec_spawnattr_getmacpolicyinfo() and before passing the @@ -753,29 +893,33 @@ mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp, off_t of struct mac_policy_conf *mpc; u_int i; - for (i = 0; i< mac_policy_list.staticmax; i++) { + for (i = 0; i < mac_policy_list.staticmax; i++) { mpc = mac_policy_list.entries[i].mpc; - if (mpc == NULL) + if (mpc == NULL) { continue; + } mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve; - if (hook == NULL) + if (hook == NULL) { continue; + } size_t spawnattrlen = 0; void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen); result = result || hook(cred, vp, offset, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen); } - if (mac_policy_list_conditional_busy() != 0) { + if (mac_policy_list_conditional_busy() != 0) { for (; i <= mac_policy_list.maxindex; i++) { mpc = mac_policy_list.entries[i].mpc; - if (mpc == NULL) + if (mpc == NULL) { continue; + } mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve; - if (hook == NULL) + if (hook == NULL) { continue; + } size_t spawnattrlen = 0; void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen); @@ -785,8 +929,9 @@ mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp, off_t of mac_policy_list_unbusy(); } } + VFS_KERNEL_DEBUG_END1(28, vp); - return (result); + return result; } int @@ -799,18 +944,21 @@ mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } /* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */ mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode); + VFS_KERNEL_DEBUG_START1(29, vp); MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask); - return (error); - } + VFS_KERNEL_DEBUG_END1(29, vp); + return error; +} int mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp) @@ -820,15 +968,18 @@ mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(30, dvp); MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label); - return (error); + VFS_KERNEL_DEBUG_END1(30, dvp); + return error; } int @@ -840,15 +991,18 @@ mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(31, dvp); MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp); - return (error); + VFS_KERNEL_DEBUG_END1(31, dvp); + return error; } int @@ -860,16 +1014,19 @@ mac_vnode_check_clone(vfs_context_t ctx, struct vnode *dvp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(32, dvp); MAC_CHECK(vnode_check_clone, cred, dvp, dvp->v_label, vp, vp->v_label, cnp); - return (error); + VFS_KERNEL_DEBUG_END1(32, dvp); + return error; } int mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp, @@ -880,15 +1037,18 @@ mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(33, dvp); MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap); - return (error); + VFS_KERNEL_DEBUG_END1(33, dvp); + return error; } int @@ -900,16 +1060,19 @@ mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(34, dvp); MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp, vp->v_label, cnp); - return (error); + VFS_KERNEL_DEBUG_END1(34, dvp); + return error; } #if 0 int @@ -921,15 +1084,18 @@ mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(35, dvp); MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type); - return (error); + VFS_KERNEL_DEBUG_END1(35, dvp); + return error; } #endif @@ -942,15 +1108,18 @@ mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(36, vp); MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name); - return (error); + VFS_KERNEL_DEBUG_END1(36, vp); + return error; } int mac_vnode_check_exchangedata(vfs_context_t ctx, @@ -961,17 +1130,20 @@ mac_vnode_check_exchangedata(vfs_context_t ctx, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); - MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label, + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(37, v1); + MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label, v2, v2->v_label); + VFS_KERNEL_DEBUG_END1(37, v1); - return (error); + return error; } #if 0 @@ -983,38 +1155,67 @@ mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(38, vp); MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type); - return (error); + VFS_KERNEL_DEBUG_END1(38, vp); + return error; } #endif int -mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp, - struct attrlist *alist) +mac_vnode_check_getattr(vfs_context_t ctx, struct ucred *file_cred, + struct vnode *vp, struct vnode_attr *va) { kauth_cred_t cred; int error; #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { return 0; + } + VFS_KERNEL_DEBUG_START1(39, vp); + MAC_CHECK(vnode_check_getattr, cred, file_cred, vp, vp->v_label, va); + VFS_KERNEL_DEBUG_END1(39, vp); + return error; +} + +int +mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp, + struct attrlist *alist) +{ + kauth_cred_t cred; + int error; +#if SECURITY_MAC_CHECK_ENFORCE + /* 21167099 - only check if we allow write */ + if (!mac_vnode_enforce) { + return 0; + } +#endif cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(40, vp); MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist); + VFS_KERNEL_DEBUG_END1(40, vp); /* Falsify results instead of returning error? */ - return (error); + return error; } int @@ -1026,8 +1227,9 @@ mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_proc_enforce || !mac_vnode_enforce) + if (!mac_proc_enforce || !mac_vnode_enforce) { return 0; + } #endif cred = vfs_context_ucred(ctx); @@ -1037,52 +1239,58 @@ mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp, * calling exec_spawnattr_getmacpolicyinfo() and before passing the * spawnattrlen as an argument to the hook. */ + VFS_KERNEL_DEBUG_START1(41, vp); { struct mac_policy_conf *mpc; u_int i; - for (i = 0; i< mac_policy_list.staticmax; i++) { + for (i = 0; i < mac_policy_list.staticmax; i++) { mpc = mac_policy_list.entries[i].mpc; - if (mpc == NULL) + if (mpc == NULL) { continue; + } mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec; - if (hook == NULL) + if (hook == NULL) { continue; + } size_t spawnattrlen = 0; void *spawnattr = exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen); error = mac_error_select( - hook(cred, - vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp, - imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags, - spawnattr, spawnattrlen), error); + hook(cred, + vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp, + imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags, + spawnattr, spawnattrlen), error); } - if (mac_policy_list_conditional_busy() != 0) { + if (mac_policy_list_conditional_busy() != 0) { for (; i <= mac_policy_list.maxindex; i++) { mpc = mac_policy_list.entries[i].mpc; - if (mpc == NULL) + if (mpc == NULL) { continue; + } mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec; - if (hook == NULL) + if (hook == NULL) { continue; + } size_t spawnattrlen = 0; void *spawnattr = exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen); error = mac_error_select( - hook(cred, - vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp, - imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags, - spawnattr, spawnattrlen), error); + hook(cred, + vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp, + imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags, + spawnattr, spawnattrlen), error); } mac_policy_list_unbusy(); } } + VFS_KERNEL_DEBUG_END1(41, vp); - return (error); + return error; } int @@ -1093,124 +1301,149 @@ mac_vnode_check_fsgetpath(vfs_context_t ctx, struct vnode *vp) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(42, vp); MAC_CHECK(vnode_check_fsgetpath, cred, vp, vp->v_label); - return (error); + VFS_KERNEL_DEBUG_END1(42, vp); + return error; } int mac_vnode_check_signature(struct vnode *vp, struct cs_blob *cs_blob, - struct image_params *imgp, - unsigned int *cs_flags, int flags) + struct image_params *imgp, + unsigned int *cs_flags, unsigned int *signer_type, + int flags, unsigned int platform) { - int error; - char *fatal_failure_desc = NULL; - size_t fatal_failure_desc_len = 0; + int error; + char *fatal_failure_desc = NULL; + size_t fatal_failure_desc_len = 0; - char *vn_path = NULL; - vm_size_t vn_pathlen = MAXPATHLEN; + char *vn_path = NULL; + vm_size_t vn_pathlen = MAXPATHLEN; + cpu_type_t cpu_type = (imgp == NULL) ? CPU_TYPE_ANY : imgp->ip_origcputype; #if SECURITY_MAC_CHECK_ENFORCE - /* 21167099 - only check if we allow write */ - if (!mac_proc_enforce || !mac_vnode_enforce) - return 0; + /* 21167099 - only check if we allow write */ + if (!mac_proc_enforce || !mac_vnode_enforce) { + return 0; + } #endif - MAC_CHECK(vnode_check_signature, vp, vp->v_label, cs_blob, - cs_flags, flags, &fatal_failure_desc, &fatal_failure_desc_len); + VFS_KERNEL_DEBUG_START1(43, vp); + MAC_CHECK(vnode_check_signature, vp, vp->v_label, cpu_type, cs_blob, + cs_flags, signer_type, flags, platform, &fatal_failure_desc, &fatal_failure_desc_len); + VFS_KERNEL_DEBUG_END1(43, vp); - if (fatal_failure_desc_len) { - // A fatal code signature validation failure occured, formulate a crash - // reason. + if (fatal_failure_desc_len) { + // A fatal code signature validation failure occured, formulate a crash + // reason. - char const *path = NULL; + char const *path = NULL; - vn_path = (char *)kalloc(MAXPATHLEN); - if (vn_path != NULL) { - if (vn_getpath(vp, vn_path, (int*)&vn_pathlen) == 0) { - path = vn_path; - } else { - path = "(get vnode path failed)"; - } - } else { - path = "(path alloc failed)"; - } - - if (error == 0) { - panic("mac_vnode_check_signature: MAC hook returned no error, " - "but status is claimed to be fatal? " - "path: '%s', fatal_failure_desc_len: %ld, fatal_failure_desc:\n%s\n", - path, fatal_failure_desc_len, fatal_failure_desc); - } - - printf("mac_vnode_check_signature: %s: code signature validation failed fatally: %s", - path, fatal_failure_desc); - - if (imgp == NULL) { - goto out; - } - - os_reason_t reason = os_reason_create(OS_REASON_CODESIGNING, - CODESIGNING_EXIT_REASON_TASKGATED_INVALID_SIG); - - if (reason == OS_REASON_NULL) { - printf("mac_vnode_check_signature: %s: failure to allocate exit reason for validation failure: %s\n", - path, fatal_failure_desc); - goto out; - } - - imgp->ip_cs_error = reason; - reason->osr_flags = (OS_REASON_FLAG_GENERATE_CRASH_REPORT | - OS_REASON_FLAG_CONSISTENT_FAILURE); - - if (fatal_failure_desc == NULL) { - // This may happen if allocation for the buffer failed. - printf("mac_vnode_check_signature: %s: fatal failure is missing its description.\n", path); - } else { - mach_vm_address_t data_addr = 0; - - int reason_error = 0; - int kcdata_error = 0; - - if ((reason_error = os_reason_alloc_buffer(reason, kcdata_estimate_required_buffer_size - (1, fatal_failure_desc_len))) == 0 && - (kcdata_error = kcdata_get_memory_addr(&reason->osr_kcd_descriptor, - EXIT_REASON_USER_DESC, fatal_failure_desc_len, - &data_addr)) == KERN_SUCCESS) { - kern_return_t mc_error = kcdata_memcpy(&reason->osr_kcd_descriptor, (mach_vm_address_t)data_addr, - fatal_failure_desc, fatal_failure_desc_len); - - if (mc_error != KERN_SUCCESS) { - printf("mac_vnode_check_signature: %s: failed to copy reason string " - "(kcdata_memcpy error: %d, length: %ld)\n", - path, mc_error, fatal_failure_desc_len); - } - } else { - printf("mac_vnode_check_signature: %s: failed to allocate space for reason string " - "(os_reason_alloc_buffer error: %d, kcdata error: %d, length: %ld)\n", - path, reason_error, kcdata_error, fatal_failure_desc_len); - } + vn_path = zalloc(ZV_NAMEI); + if (vn_getpath(vp, vn_path, (int*)&vn_pathlen) == 0) { + path = vn_path; + } else { + path = "(get vnode path failed)"; + } + + if (error == 0) { + panic("mac_vnode_check_signature: MAC hook returned no error, " + "but status is claimed to be fatal? " + "path: '%s', fatal_failure_desc_len: %ld, fatal_failure_desc:\n%s\n", + path, fatal_failure_desc_len, fatal_failure_desc); + } + + printf("mac_vnode_check_signature: %s: code signature validation failed fatally: %s", + path, fatal_failure_desc); - } - } + if (imgp == NULL) { + goto out; + } + + os_reason_t reason = os_reason_create(OS_REASON_CODESIGNING, + CODESIGNING_EXIT_REASON_TASKGATED_INVALID_SIG); + + if (reason == OS_REASON_NULL) { + printf("mac_vnode_check_signature: %s: failure to allocate exit reason for validation failure: %s\n", + path, fatal_failure_desc); + goto out; + } + + imgp->ip_cs_error = reason; + reason->osr_flags = (OS_REASON_FLAG_GENERATE_CRASH_REPORT | + OS_REASON_FLAG_CONSISTENT_FAILURE); + + if (fatal_failure_desc == NULL) { + // This may happen if allocation for the buffer failed. + printf("mac_vnode_check_signature: %s: fatal failure is missing its description.\n", path); + } else { + mach_vm_address_t data_addr = 0; + + int reason_error = 0; + int kcdata_error = 0; + + if ((reason_error = os_reason_alloc_buffer_noblock(reason, kcdata_estimate_required_buffer_size + (1, (uint32_t)fatal_failure_desc_len))) == 0 && + (kcdata_error = kcdata_get_memory_addr(&reason->osr_kcd_descriptor, + EXIT_REASON_USER_DESC, (uint32_t)fatal_failure_desc_len, + &data_addr)) == KERN_SUCCESS) { + kern_return_t mc_error = kcdata_memcpy(&reason->osr_kcd_descriptor, (mach_vm_address_t)data_addr, + fatal_failure_desc, (uint32_t)fatal_failure_desc_len); + + if (mc_error != KERN_SUCCESS) { + printf("mac_vnode_check_signature: %s: failed to copy reason string " + "(kcdata_memcpy error: %d, length: %ld)\n", + path, mc_error, fatal_failure_desc_len); + } + } else { + printf("mac_vnode_check_signature: %s: failed to allocate space for reason string " + "(os_reason_alloc_buffer error: %d, kcdata error: %d, length: %ld)\n", + path, reason_error, kcdata_error, fatal_failure_desc_len); + } + } + } out: - if (vn_path) { - kfree(vn_path, MAXPATHLEN); - } + if (vn_path) { + zfree(ZV_NAMEI, vn_path); + } + + if (fatal_failure_desc_len > 0 && fatal_failure_desc != NULL) { + /* AMFI uses kalloc() which for kexts is redirected to KHEAP_KEXT */ + kheap_free(KHEAP_KEXT, fatal_failure_desc, fatal_failure_desc_len); + } + + return error; +} - if (fatal_failure_desc_len > 0 && fatal_failure_desc != NULL) { - kfree(fatal_failure_desc, fatal_failure_desc_len); - } +int +mac_vnode_check_supplemental_signature(struct vnode *vp, + struct cs_blob *cs_blob, struct vnode *linked_vp, + struct cs_blob *linked_cs_blob, unsigned int *signer_type) +{ + int error; + +#if SECURITY_MAC_CHECK_ENFORCE + /* 21167099 - only check if we allow write */ + if (!mac_proc_enforce || !mac_vnode_enforce) { + return 0; + } +#endif + VFS_KERNEL_DEBUG_START1(93, vp); + MAC_CHECK(vnode_check_supplemental_signature, vp, vp->v_label, cs_blob, linked_vp, linked_cs_blob, + signer_type); + VFS_KERNEL_DEBUG_END1(93, vp); - return (error); + return error; } #if 0 @@ -1222,15 +1455,18 @@ mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(44, vp); MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type); - return (error); + VFS_KERNEL_DEBUG_END1(44, vp); + return error; } #endif @@ -1243,35 +1479,41 @@ mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(45, vp); MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label, name, uio); - return (error); + VFS_KERNEL_DEBUG_END1(45, vp); + return error; } int -mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd) +mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_long cmd) { kauth_cred_t cred; int error; #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(46, vp); MAC_CHECK(vnode_check_ioctl, cred, vp, vp->v_label, cmd); - return (error); + VFS_KERNEL_DEBUG_END1(46, vp); + return error; } int @@ -1283,17 +1525,20 @@ mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(47, vp); MAC_CHECK(vnode_check_kqfilter, cred, file_cred, kn, vp, vp->v_label); + VFS_KERNEL_DEBUG_END1(47, vp); - return (error); + return error; } int @@ -1305,16 +1550,19 @@ mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(48, vp); MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp, vp->v_label, cnp); - return (error); + VFS_KERNEL_DEBUG_END1(48, vp); + return error; } int @@ -1325,15 +1573,41 @@ mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { return 0; + } + VFS_KERNEL_DEBUG_START1(49, vp); + MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label); + VFS_KERNEL_DEBUG_END1(49, vp); + return error; +} + +int +mac_vnode_check_lookup_preflight(vfs_context_t ctx, struct vnode *dvp, + const char *path, size_t pathlen) +{ + kauth_cred_t cred; + int error; +#if SECURITY_MAC_CHECK_ENFORCE + /* 21167099 - only check if we allow write */ + if (!mac_vnode_enforce) { + return 0; + } +#endif cred = vfs_context_ucred(ctx); - MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label); - return (error); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(50, dvp); + MAC_CHECK(vnode_check_lookup_preflight, cred, dvp, dvp->v_label, path, pathlen); + VFS_KERNEL_DEBUG_END1(50, dvp); + return error; } int @@ -1345,15 +1619,18 @@ mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(51, dvp); MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp); - return (error); + VFS_KERNEL_DEBUG_END1(51, dvp); + return error; } int @@ -1364,15 +1641,18 @@ mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(52, vp); MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode); - return (error); + VFS_KERNEL_DEBUG_END1(52, vp); + return error; } int @@ -1384,17 +1664,20 @@ mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(53, vp); MAC_CHECK(vnode_check_read, cred, file_cred, vp, vp->v_label); + VFS_KERNEL_DEBUG_END1(53, vp); - return (error); + return error; } int @@ -1405,15 +1688,18 @@ mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(54, dvp); MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label); - return (error); + VFS_KERNEL_DEBUG_END1(54, dvp); + return error; } int @@ -1424,15 +1710,18 @@ mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(55, vp); MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label); - return (error); + VFS_KERNEL_DEBUG_END1(55, vp); + return error; } int @@ -1444,16 +1733,19 @@ mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(56, vp); MAC_CHECK(vnode_check_label_update, cred, vp, vp->v_label, newlabel); + VFS_KERNEL_DEBUG_END1(56, vp); - return (error); + return error; } int @@ -1466,28 +1758,35 @@ mac_vnode_check_rename(vfs_context_t ctx, struct vnode *dvp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(57, vp); MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp, vp->v_label, cnp); - if (error) - return (error); + if (error) { + VFS_KERNEL_DEBUG_END1(57, vp); + return error; + } MAC_CHECK(vnode_check_rename_to, cred, tdvp, tdvp->v_label, tvp, tvp != NULL ? tvp->v_label : NULL, dvp == tdvp, tcnp); - if (error) - return (error); + if (error) { + VFS_KERNEL_DEBUG_END1(57, vp); + return error; + } MAC_CHECK(vnode_check_rename, cred, dvp, dvp->v_label, vp, vp->v_label, cnp, tdvp, tdvp->v_label, tvp, tvp != NULL ? tvp->v_label : NULL, tcnp); - return (error); + VFS_KERNEL_DEBUG_END1(57, vp); + return error; } int @@ -1498,15 +1797,18 @@ mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(58, vp); MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label); - return (error); + VFS_KERNEL_DEBUG_END1(58, vp); + return error; } int @@ -1517,15 +1819,18 @@ mac_vnode_check_searchfs(vfs_context_t ctx, struct vnode *vp, struct attrlist *a #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(59, vp); MAC_CHECK(vnode_check_searchfs, cred, vp, vp->v_label, alist); - return (error); + VFS_KERNEL_DEBUG_END1(59, vp); + return error; } int @@ -1536,15 +1841,18 @@ mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(60, vp); MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which); - return (error); + VFS_KERNEL_DEBUG_END1(60, vp); + return error; } int @@ -1556,15 +1864,18 @@ mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(61, vp); MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, acl); - return (error); + VFS_KERNEL_DEBUG_END1(61, vp); + return error; } int @@ -1576,15 +1887,18 @@ mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(62, vp); MAC_CHECK(vnode_check_setattrlist, cred, vp, vp->v_label, alist); - return (error); + VFS_KERNEL_DEBUG_END1(62, vp); + return error; } int @@ -1596,16 +1910,19 @@ mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(63, vp); MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label, name, uio); - return (error); + VFS_KERNEL_DEBUG_END1(63, vp); + return error; } int @@ -1616,15 +1933,18 @@ mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(64, vp); MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags); - return (error); + VFS_KERNEL_DEBUG_END1(64, vp); + return error; } int @@ -1635,15 +1955,18 @@ mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(65, vp); MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode); - return (error); + VFS_KERNEL_DEBUG_END1(65, vp); + return error; } int @@ -1655,15 +1978,18 @@ mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(66, vp); MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid); - return (error); + VFS_KERNEL_DEBUG_END1(66, vp); + return error; } int @@ -1675,16 +2001,19 @@ mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(67, vp); MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime, mtime); - return (error); + VFS_KERNEL_DEBUG_END1(67, vp); + return error; } int @@ -1696,38 +2025,67 @@ mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(68, vp); MAC_CHECK(vnode_check_stat, cred, file_cred, vp, vp->v_label); - return (error); + VFS_KERNEL_DEBUG_END1(68, vp); + return error; } int -mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred, - struct vnode *vp) +mac_vnode_check_trigger_resolve(vfs_context_t ctx, struct vnode *dvp, + struct componentname *cnp) { kauth_cred_t cred; int error; #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { return 0; + } + VFS_KERNEL_DEBUG_START1(69, dvp); + MAC_CHECK(vnode_check_trigger_resolve, cred, dvp, dvp->v_label, cnp); + VFS_KERNEL_DEBUG_END1(69, dvp); + return error; +} +int +mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred, + struct vnode *vp) +{ + kauth_cred_t cred; + int error; + +#if SECURITY_MAC_CHECK_ENFORCE + /* 21167099 - only check if we allow write */ + if (!mac_vnode_enforce) { + return 0; + } +#endif cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(70, vp); MAC_CHECK(vnode_check_truncate, cred, file_cred, vp, vp->v_label); + VFS_KERNEL_DEBUG_END1(70, vp); - return (error); + return error; } int @@ -1739,16 +2097,19 @@ mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(71, vp); MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label); + VFS_KERNEL_DEBUG_END1(71, vp); - return (error); + return error; } int @@ -1760,15 +2121,18 @@ mac_vnode_check_uipc_bind(vfs_context_t ctx, struct vnode *dvp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(72, dvp); MAC_CHECK(vnode_check_uipc_bind, cred, dvp, dvp->v_label, cnp, vap); - return (error); + VFS_KERNEL_DEBUG_END1(72, dvp); + return error; } int @@ -1779,15 +2143,18 @@ mac_vnode_check_uipc_connect(vfs_context_t ctx, struct vnode *vp, struct socket #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(73, vp); MAC_CHECK(vnode_check_uipc_connect, cred, vp, vp->v_label, (socket_t) so); - return (error); + VFS_KERNEL_DEBUG_END1(73, vp); + return error; } void @@ -1796,8 +2163,9 @@ mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlab kauth_cred_t cred = vfs_context_ucred(ctx); struct label *tmpl = NULL; - if (vp->v_label == NULL) + if (vp->v_label == NULL) { tmpl = mac_vnode_label_alloc(); + } vnode_lock(vp); @@ -1807,11 +2175,14 @@ mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlab tmpl = NULL; } + VFS_KERNEL_DEBUG_START1(74, vp); MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel); + VFS_KERNEL_DEBUG_END1(74, vp); vnode_unlock(vp); - if (tmpl != NULL) + if (tmpl != NULL) { mac_vnode_label_free(tmpl); + } } int @@ -1821,13 +2192,16 @@ mac_vnode_find_sigs(struct proc *p, struct vnode *vp, off_t offset) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_proc_enforce || !mac_vnode_enforce) + if (!mac_proc_enforce || !mac_vnode_enforce) { return 0; + } #endif + VFS_KERNEL_DEBUG_START1(75, vp); MAC_CHECK(vnode_find_sigs, p, vp, offset, vp->v_label); + VFS_KERNEL_DEBUG_END1(75, vp); - return (error); + return error; } void @@ -1838,44 +2212,53 @@ mac_mount_label_associate(vfs_context_t ctx, struct mount *mp) /* XXX: eventually this logic may be handled by the policy? */ /* We desire MULTILABEL for the root filesystem. */ - if ((mp->mnt_flag & MNT_ROOTFS) && - (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0)) + if ((mp->mnt_flag & MNT_ROOTFS) && + (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0)) { mp->mnt_flag |= MNT_MULTILABEL; + } /* MULTILABEL on DEVFS. */ - if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0) + if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0) { mp->mnt_flag |= MNT_MULTILABEL; + } /* MULTILABEL on FDESC pseudo-filesystem. */ - if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0) + if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0) { mp->mnt_flag |= MNT_MULTILABEL; + } /* MULTILABEL on all NFS filesystems. */ - if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0) + if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0) { mp->mnt_flag |= MNT_MULTILABEL; + } /* MULTILABEL on all AFP filesystems. */ - if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0) + if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0) { mp->mnt_flag |= MNT_MULTILABEL; + } if (mp->mnt_vtable != NULL) { /* Any filesystem that supports native XATTRs. */ - if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR)) + if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR)) { mp->mnt_flag |= MNT_MULTILABEL; + } /* Filesystem does not support multilabel. */ if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) && - (mp->mnt_flag & MNT_MULTILABEL)) + (mp->mnt_flag & MNT_MULTILABEL)) { mp->mnt_flag &= ~MNT_MULTILABEL; + } } + VFS_KERNEL_DEBUG_START1(76, mp); MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel); + VFS_KERNEL_DEBUG_END1(76, mp); #if DEBUG printf("MAC Framework enabling %s support: %s -> %s (%s)\n", - mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel", - mp->mnt_vfsstat.f_mntfromname, - mp->mnt_vfsstat.f_mntonname, - mp->mnt_vfsstat.f_fstypename); + mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel", + mp->mnt_vfsstat.f_mntfromname, + mp->mnt_vfsstat.f_mntonname, + mp->mnt_vfsstat.f_fstypename); #endif } @@ -1888,16 +2271,42 @@ mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { return 0; + } + VFS_KERNEL_DEBUG_START1(77, vp); + MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name); + VFS_KERNEL_DEBUG_END1(77, vp); + + return error; +} +int +mac_mount_check_mount_late(vfs_context_t ctx, struct mount *mp) +{ + kauth_cred_t cred; + int error; + +#if SECURITY_MAC_CHECK_ENFORCE + /* 21167099 - only check if we allow write */ + if (!mac_vnode_enforce) { + return 0; + } +#endif cred = vfs_context_ucred(ctx); - MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(78, mp); + MAC_CHECK(mount_check_mount_late, cred, mp); + VFS_KERNEL_DEBUG_END1(78, mp); - return (error); + return error; } int @@ -1909,15 +2318,18 @@ mac_mount_check_snapshot_create(vfs_context_t ctx, struct mount *mp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(79, mp); MAC_CHECK(mount_check_snapshot_create, cred, mp, name); - return (error); + VFS_KERNEL_DEBUG_END1(79, mp); + return error; } int @@ -1929,35 +2341,87 @@ mac_mount_check_snapshot_delete(vfs_context_t ctx, struct mount *mp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { return 0; + } + VFS_KERNEL_DEBUG_START1(80, mp); + MAC_CHECK(mount_check_snapshot_delete, cred, mp, name); + VFS_KERNEL_DEBUG_END1(80, mp); + return error; +} +int +mac_mount_check_snapshot_mount(vfs_context_t ctx, struct vnode *rvp, struct vnode *vp, struct componentname *cnp, + const char *name, const char *vfc_name) +{ + kauth_cred_t cred; + int error; + +#if SECURITY_MAC_CHECK_ENFORCE + /* 21167099 - only check if we allow write */ + if (!mac_vnode_enforce) { + return 0; + } +#endif cred = vfs_context_ucred(ctx); - MAC_CHECK(mount_check_snapshot_delete, cred, mp, name); - return (error); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(92, vp); + MAC_CHECK(mount_check_snapshot_mount, cred, rvp, vp, cnp, name, vfc_name); + VFS_KERNEL_DEBUG_END1(92, vp); + return error; } int -mac_mount_check_remount(vfs_context_t ctx, struct mount *mp) +mac_mount_check_snapshot_revert(vfs_context_t ctx, struct mount *mp, + const char *name) { kauth_cred_t cred; int error; #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { return 0; + } + VFS_KERNEL_DEBUG_START1(81, mp); + MAC_CHECK(mount_check_snapshot_revert, cred, mp, name); + VFS_KERNEL_DEBUG_END1(81, mp); + return error; +} +int +mac_mount_check_remount(vfs_context_t ctx, struct mount *mp) +{ + kauth_cred_t cred; + int error; + +#if SECURITY_MAC_CHECK_ENFORCE + /* 21167099 - only check if we allow write */ + if (!mac_vnode_enforce) { + return 0; + } +#endif cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(82, mp); MAC_CHECK(mount_check_remount, cred, mp, mp->mnt_mntlabel); + VFS_KERNEL_DEBUG_END1(82, mp); - return (error); + return error; } int @@ -1968,20 +2432,23 @@ mac_mount_check_umount(vfs_context_t ctx, struct mount *mp) #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(83, mp); MAC_CHECK(mount_check_umount, cred, mp, mp->mnt_mntlabel); + VFS_KERNEL_DEBUG_END1(83, mp); - return (error); + return error; } int -mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp, +mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp, struct vfs_attr *vfa) { kauth_cred_t cred; @@ -1989,19 +2456,22 @@ mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(84, mp); MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa); - return (error); + VFS_KERNEL_DEBUG_END1(84, mp); + return error; } int -mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp, +mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp, struct vfs_attr *vfa) { kauth_cred_t cred; @@ -2009,15 +2479,18 @@ mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp, #if SECURITY_MAC_CHECK_ENFORCE /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) + if (!mac_vnode_enforce) { return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(85, mp); MAC_CHECK(mount_check_setattr, cred, mp, mp->mnt_mntlabel, vfa); - return (error); + VFS_KERNEL_DEBUG_END1(85, mp); + return error; } int @@ -2027,17 +2500,20 @@ mac_mount_check_stat(vfs_context_t ctx, struct mount *mount) int error; #if SECURITY_MAC_CHECK_ENFORCE - /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) - return 0; + /* 21167099 - only check if we allow write */ + if (!mac_vnode_enforce) { + return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(86, mount); MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel); + VFS_KERNEL_DEBUG_END1(86, mount); - return (error); + return error; } int @@ -2047,37 +2523,43 @@ mac_mount_check_label_update(vfs_context_t ctx, struct mount *mount) int error; #if SECURITY_MAC_CHECK_ENFORCE - /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) - return 0; + /* 21167099 - only check if we allow write */ + if (!mac_vnode_enforce) { + return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(87, mount); MAC_CHECK(mount_check_label_update, cred, mount, mount->mnt_mntlabel); + VFS_KERNEL_DEBUG_END1(87, mount); - return (error); + return error; } int -mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd) +mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_long cmd) { kauth_cred_t cred; int error; #if SECURITY_MAC_CHECK_ENFORCE - /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) - return 0; + /* 21167099 - only check if we allow write */ + if (!mac_vnode_enforce) { + return 0; + } #endif - if (!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) - return 0; - cred = vfs_context_ucred(ctx); + if (!mac_cred_check_enforce(cred)) { + return 0; + } + VFS_KERNEL_DEBUG_START1(88, mp); MAC_CHECK(mount_check_fsctl, cred, mp, mp->mnt_mntlabel, cmd); + VFS_KERNEL_DEBUG_END1(88, mp); - return (error); + return error; } void @@ -2085,13 +2567,16 @@ mac_devfs_label_associate_device(dev_t dev, struct devnode *de, const char *fullpath) { #if SECURITY_MAC_CHECK_ENFORCE - /* 21167099 - only check if we allow write */ - if (!mac_device_enforce) - return; + /* 21167099 - only check if we allow write */ + if (!mac_device_enforce) { + return; + } #endif + VFS_KERNEL_DEBUG_START1(89, de); MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label, fullpath); + VFS_KERNEL_DEBUG_END1(89, de); } void @@ -2099,13 +2584,16 @@ mac_devfs_label_associate_directory(const char *dirname, int dirnamelen, struct devnode *de, const char *fullpath) { #if SECURITY_MAC_CHECK_ENFORCE - /* 21167099 - only check if we allow write */ - if (!mac_device_enforce) - return; + /* 21167099 - only check if we allow write */ + if (!mac_device_enforce) { + return; + } #endif + VFS_KERNEL_DEBUG_START1(90, de); MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de, de->dn_label, fullpath); + VFS_KERNEL_DEBUG_END1(90, de); } int @@ -2114,22 +2602,26 @@ vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context) int error; #if SECURITY_MAC_CHECK_ENFORCE - /* 21167099 - only check if we allow write */ - if (!mac_vnode_enforce) - return 0; + /* 21167099 - only check if we allow write */ + if (!mac_vnode_enforce) { + return 0; + } #endif - if (!mac_label_vnodes) - return (0); + if (!mac_label_vnodes) { + return 0; + } if (vp->v_mount == NULL) { printf("vn_setlabel: null v_mount\n"); - if (vp->v_type != VNON) + if (vp->v_type != VNON) { printf("vn_setlabel: null v_mount with non-VNON\n"); - return (EBADF); + } + return EBADF; } - if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) - return (ENOTSUP); + if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) { + return ENOTSUP; + } /* * Multi-phase commit. First check the policies to confirm the @@ -2138,26 +2630,26 @@ vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context) * should update the vnode at the end as part of VNOP_SETLABEL()? */ error = mac_vnode_check_label_update(context, vp, intlabel); - if (error) - return (error); + if (error) { + return error; + } error = VNOP_SETLABEL(vp, intlabel, context); if (error == ENOTSUP) { error = mac_vnode_label_store(context, vp, - intlabel); + intlabel); if (error) { printf("%s: mac_vnode_label_store failed %d\n", - __func__, error); - return (error); + __func__, error); + return error; } mac_vnode_label_update(context, vp, intlabel); - } else - if (error) { + } else if (error) { printf("vn_setlabel: vop setlabel failed %d\n", error); - return (error); + return error; } - return (0); + return 0; } int @@ -2175,39 +2667,49 @@ mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp, error = 0; + VFS_KERNEL_DEBUG_START1(91, vp); /* * If no backing file, let the policy choose which label to use. */ if (fnp->fd_fd == -1) { MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx), mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label); - return (0); + VFS_KERNEL_DEBUG_END1(91, vp); + return 0; } p = vfs_context_proc(ctx); error = fp_lookup(p, fnp->fd_fd, &fp, 0); - if (error) - return (error); + if (error) { + VFS_KERNEL_DEBUG_END1(91, vp); + return error; + } - if (fp->f_fglob == NULL) { + if (fp->fp_glob == NULL) { error = EBADF; goto out; } - switch (FILEGLOB_DTYPE(fp->f_fglob)) { + switch (FILEGLOB_DTYPE(fp->fp_glob)) { case DTYPE_VNODE: - fvp = (struct vnode *)fp->f_fglob->fg_data; - if ((error = vnode_getwithref(fvp))) + fvp = (struct vnode *)fp->fp_glob->fg_data; + if ((error = vnode_getwithref(fvp))) { goto out; - MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label); + } + if (fvp->v_label != NULL) { + if (mac_label_vnodes != 0 && vp->v_label == NULL) { + mac_vnode_label_init(vp); /* init dst label */ + } + MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label); + } (void)vnode_put(fvp); break; #if CONFIG_MACF_SOCKET_SUBSET case DTYPE_SOCKET: - so = (struct socket *)fp->f_fglob->fg_data; + so = (struct socket *)fp->fp_glob->fg_data; socket_lock(so, 1); MAC_PERFORM(vnode_label_associate_socket, - vfs_context_ucred(ctx), (socket_t)so, so->so_label, + vfs_context_ucred(ctx), (socket_t)so, so->so_label, vp, vp->v_label); socket_unlock(so, 1); break; @@ -2219,7 +2721,7 @@ mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp, psem_label_associate(fp, vp, ctx); break; case DTYPE_PIPE: - cpipe = (struct pipe *)fp->f_fglob->fg_data; + cpipe = (struct pipe *)fp->fp_glob->fg_data; /* kern/sys_pipe.c:pipe_select() suggests this test. */ if (cpipe == (struct pipe *)-1) { error = EINVAL; @@ -2236,11 +2738,47 @@ mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp, case DTYPE_NETPOLICY: default: MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx), - mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label, + mp, mp->mnt_mntlabel, fp->fp_glob, fp->fp_glob->fg_label, vp, vp->v_label); break; } out: + VFS_KERNEL_DEBUG_END1(91, vp); fp_drop(p, fnp->fd_fd, fp, 0); - return (error); + return error; +} + +intptr_t +mac_vnode_label_get(struct vnode *vp, int slot, intptr_t sentinel) +{ + struct label *l; + + KASSERT(vp != NULL, ("mac_vnode_label_get: NULL vnode")); + l = vp->v_label; + if (l != NULL) { + return mac_label_get(l, slot); + } else { + return sentinel; + } +} + +void +mac_vnode_label_set(struct vnode *vp, int slot, intptr_t v) +{ + struct label *l; + KASSERT(vp != NULL, ("mac_vnode_label_set: NULL vnode")); + l = vp->v_label; + if (l == NULL) { + mac_vnode_label_init(vp); + l = vp->v_label; + } + mac_label_set(l, slot, v); +} + +void +mac_vnode_notify_reclaim(struct vnode *vp) +{ + VFS_KERNEL_DEBUG_START1(94, vp); + MAC_PERFORM(vnode_notify_reclaim, vp); + VFS_KERNEL_DEBUG_END1(94, vp); }