X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/2d21ac55c334faf3a56e5634905ed6987fc787d4..HEAD:/security/mac_vfs_subr.c diff --git a/security/mac_vfs_subr.c b/security/mac_vfs_subr.c index e418342b0..3fb5132d5 100644 --- a/security/mac_vfs_subr.c +++ b/security/mac_vfs_subr.c @@ -2,7 +2,7 @@ * Copyright (c) 2007 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@ */ #include @@ -34,34 +34,51 @@ #include #include #include +#include "../bsd/sys/fsevents.h" #include /* - * Caller holds reference or sets VNODE_LABEL_NEEDREF to non-zero. - * - * Function will drop lock and reference on return. + * Caller holds I/O reference on vnode */ int vnode_label(struct mount *mp, struct vnode *dvp, struct vnode *vp, - struct componentname *cnp, int flags, vfs_context_t ctx) + struct componentname *cnp, int flags, vfs_context_t ctx) { - int error; - - error = 0; - - vnode_lock(vp); + int error = 0; + bool exit_fast; + + /* fast path checks... */ + + /* are we labeling vnodes? If not still notify of create */ +#if CONFIG_MACF_LAZY_VNODE_LABELS + exit_fast = true; +#else + exit_fast = (mac_label_vnodes == 0); +#endif + if (exit_fast) { + if (flags & VNODE_LABEL_CREATE) { + error = mac_vnode_notify_create(ctx, + mp, dvp, vp, cnp); + } + return 0; + } + /* if already VL_LABELED */ if (vp->v_lflag & VL_LABELED) { - if (!(flags & VNODE_LABEL_NEEDREF)) - vnode_put_locked(vp); - vnode_unlock(vp); - return (0); + return 0; } - if ((flags & VNODE_LABEL_NEEDREF) && vnode_get_locked(vp)) { + vnode_lock_spin(vp); + + /* + * must revalidate state once we hold the lock + * since we could have blocked and someone else + * has since labeled this vnode + */ + if (vp->v_lflag & VL_LABELED) { vnode_unlock(vp); - return (ENOENT); + return 0; } if ((vp->v_lflag & VL_LABEL) == 0) { @@ -69,23 +86,29 @@ vnode_label(struct mount *mp, struct vnode *dvp, struct vnode *vp, /* Could sleep on disk I/O, drop lock. */ vnode_unlock(vp); - if (flags & VNODE_LABEL_CREATE) + + if (vp->v_label == NULL) { + vp->v_label = mac_vnode_label_alloc(); + } + + if (flags & VNODE_LABEL_CREATE) { error = mac_vnode_notify_create(ctx, mp, dvp, vp, cnp); - else + } else { error = mac_vnode_label_associate(mp, vp, ctx); - vnode_lock(vp); + } - if ((error == 0) && (vp->v_flag & VNCACHEABLE)) + vnode_lock_spin(vp); + + if ((error == 0) && (vp->v_flag & VNCACHEABLE)) { vp->v_lflag |= VL_LABELED; + } vp->v_lflag &= ~VL_LABEL; if (vp->v_lflag & VL_LABELWAIT) { vp->v_lflag &= ~VL_LABELWAIT; - wakeup(vp->v_label); + wakeup(&vp->v_label); } - vnode_put_locked(vp); - vnode_unlock(vp); } else { struct timespec ts; @@ -94,20 +117,21 @@ vnode_label(struct mount *mp, struct vnode *dvp, struct vnode *vp, while (vp->v_lflag & VL_LABEL) { vp->v_lflag |= VL_LABELWAIT; - error = msleep(vp->v_label, &vp->v_lock, PVFS|PDROP, + + error = msleep(&vp->v_label, &vp->v_lock, PVFS | PDROP, "vnode_label", &ts); - vnode_lock(vp); + vnode_lock_spin(vp); + if (error == EWOULDBLOCK) { vprint("vnode label timeout", vp); break; } } /* XXX: what should be done if labeling failed (above)? */ - vnode_put_locked(vp); - vnode_unlock(vp); } + vnode_unlock(vp); - return (error); + return error; } @@ -122,11 +146,10 @@ vnode_label(struct mount *mp, struct vnode *dvp, struct vnode *vp, void vnode_relabel(struct vnode *vp) { - /* Wait for any other labeling to complete. */ while (vp->v_lflag & VL_LABEL) { vp->v_lflag |= VL_LABELWAIT; - (void)msleep(vp->v_label, &vp->v_lock, PVFS, "vnode_relabel", 0); + (void)msleep(&vp->v_label, &vp->v_lock, PVFS, "vnode_relabel", 0); } /* Clear labeled flag */ @@ -140,58 +163,74 @@ vnode_relabel(struct vnode *vp) */ int -mac_vnop_setxattr (struct vnode *vp, const char *name, char *buf, size_t len) +mac_vnop_setxattr(struct vnode *vp, const char *name, char *buf, size_t len) { vfs_context_t ctx; int options = XATTR_NOSECURITY; - char uio_buf[ UIO_SIZEOF(1) ]; - uio_t auio; + char uio_buf[UIO_SIZEOF(1)]; + uio_t auio; int error; - if (vfs_isrdonly(vp->v_mount)) - return (EROFS); + if (vfs_isrdonly(vp->v_mount)) { + return EROFS; + } ctx = vfs_context_current(); auio = uio_createwithbuffer(1, 0, UIO_SYSSPACE, UIO_WRITE, - &uio_buf[0], sizeof(uio_buf)); + &uio_buf[0], sizeof(uio_buf)); uio_addiov(auio, CAST_USER_ADDR_T(buf), len); error = vn_setxattr(vp, name, auio, options, ctx); +#if CONFIG_FSE + if (error == 0) { + add_fsevent(FSE_XATTR_MODIFIED, ctx, + FSE_ARG_VNODE, vp, + FSE_ARG_DONE); + } +#endif - return (error); + return error; } int -mac_vnop_getxattr (struct vnode *vp, const char *name, char *buf, size_t len, - size_t *attrlen) +mac_vnop_getxattr(struct vnode *vp, const char *name, char *buf, size_t len, + size_t *attrlen) { vfs_context_t ctx = vfs_context_current(); int options = XATTR_NOSECURITY; - char uio_buf[ UIO_SIZEOF(1) ]; - uio_t auio; + char uio_buf[UIO_SIZEOF(1)]; + uio_t auio; int error; auio = uio_createwithbuffer(1, 0, UIO_SYSSPACE, UIO_READ, - &uio_buf[0], sizeof(uio_buf)); + &uio_buf[0], sizeof(uio_buf)); uio_addiov(auio, CAST_USER_ADDR_T(buf), len); error = vn_getxattr(vp, name, auio, attrlen, options, ctx); *attrlen = len - uio_resid(auio); - return (error); + return error; } int -mac_vnop_removexattr (struct vnode *vp, const char *name) +mac_vnop_removexattr(struct vnode *vp, const char *name) { vfs_context_t ctx = vfs_context_current(); int options = XATTR_NOSECURITY; int error; - if (vfs_isrdonly(vp->v_mount)) - return (EROFS); + if (vfs_isrdonly(vp->v_mount)) { + return EROFS; + } error = vn_removexattr(vp, name, options, ctx); +#if CONFIG_FSE + if (error == 0) { + add_fsevent(FSE_XATTR_REMOVED, ctx, + FSE_ARG_VNODE, vp, + FSE_ARG_DONE); + } +#endif - return (error); + return error; }