X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/2d21ac55c334faf3a56e5634905ed6987fc787d4..4b17d6b6e417f714551ec129064745ea9919780e:/security/mac_vfs.c diff --git a/security/mac_vfs.c b/security/mac_vfs.c index 4316e2d3b..7bf550622 100644 --- a/security/mac_vfs.c +++ b/security/mac_vfs.c @@ -79,7 +79,7 @@ #include #include -#include +#include #include @@ -139,10 +139,15 @@ mac_vnode_label_alloc(void) void mac_vnode_label_init(vnode_t vp) { - vp->v_label = mac_vnode_label_alloc(); } +int +mac_vnode_label_init_needed(vnode_t vp) +{ + return (mac_label_vnodes != 0 && vp->v_label == NULL); +} + /* * 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 @@ -182,8 +187,6 @@ mac_mount_label_free(struct label *label) void mac_mount_label_destroy(struct mount *mp) { - - if (mp->mnt_mntlabel != NULL) { mac_mount_label_free(mp->mnt_mntlabel); mp->mnt_mntlabel = NULL; @@ -193,7 +196,6 @@ 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); } @@ -202,17 +204,21 @@ mac_vnode_label_free(struct label *label) void mac_vnode_label_destroy(struct vnode *vp) { - - mac_vnode_label_free(vp->v_label); - vp->v_label = NULL; + if (vp->v_label != NULL) { + mac_vnode_label_free(vp->v_label); + vp->v_label = NULL; + } } #endif void mac_vnode_label_copy(struct label *src, struct label *dest) { - - MAC_PERFORM(vnode_label_copy, src, dest); + if (src == NULL) { + MAC_PERFORM(vnode_label_init, dest); + } else { + MAC_PERFORM(vnode_label_copy, src, dest); + } } int @@ -346,7 +352,7 @@ void mac_vnode_label_associate_singlelabel(struct mount *mp, struct vnode *vp) { - if (!mac_vnode_enforce) + if (!mac_vnode_enforce || !mac_label_vnodes) return; MAC_PERFORM(vnode_label_associate_singlelabel, mp, @@ -371,6 +377,34 @@ mac_vnode_notify_create(vfs_context_t ctx, struct mount *mp, return (error); } +void +mac_vnode_notify_rename(vfs_context_t ctx, struct vnode *vp, + struct vnode *dvp, struct componentname *cnp) +{ + kauth_cred_t cred; + + if (!mac_vnode_enforce || + !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + return; + + cred = vfs_context_ucred(ctx); + MAC_PERFORM(vnode_notify_rename, cred, vp, vp->v_label, + dvp, dvp->v_label, cnp); +} + +void +mac_vnode_notify_open(vfs_context_t ctx, struct vnode *vp, int acc_flags) +{ + kauth_cred_t cred; + + if (!mac_vnode_enforce || + !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + return; + + cred = vfs_context_ucred(ctx); + MAC_PERFORM(vnode_notify_open, cred, vp, vp->v_label, acc_flags); +} + /* * Extended attribute 'name' was updated via * vn_setxattr() or vn_removexattr(). Allow the @@ -382,7 +416,7 @@ mac_vnode_label_update_extattr(struct mount *mp, struct vnode *vp, { int error = 0; - if (!mac_vnode_enforce) + if (!mac_vnode_enforce || !mac_label_vnodes) return; MAC_PERFORM(vnode_label_update_extattr, mp, mp->mnt_mntlabel, vp, @@ -403,7 +437,7 @@ mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp, kauth_cred_t cred; int error; - if (!mac_vnode_enforce && + if (!mac_vnode_enforce || !mac_label_vnodes || !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) return 0; @@ -413,21 +447,25 @@ mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp, return (error); } -void +int mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp, struct label *scriptvnodelabel, struct label *execl) { kauth_cred_t cred; + int disjoint = 0; + posix_cred_t pcred = posix_cred_get(new); if (!mac_proc_enforce && !mac_vnode_enforce) - return; + return disjoint; /* mark the new cred to indicate "matching" includes the label */ - new->cr_flags |= CRF_MAC_ENFORCE; + pcred->cr_flags |= CRF_MAC_ENFORCE; cred = vfs_context_ucred(ctx); MAC_PERFORM(cred_label_update_execve, cred, new, vp, vp->v_label, - scriptvnodelabel, execl); + scriptvnodelabel, execl, &disjoint); + + return (disjoint); } int @@ -633,6 +671,34 @@ mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp, return (error); } +int +mac_vnode_check_fsgetpath(vfs_context_t ctx, struct vnode *vp) +{ + kauth_cred_t cred; + int error; + + if (!mac_vnode_enforce || + !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + return (0); + + cred = vfs_context_ucred(ctx); + MAC_CHECK(vnode_check_fsgetpath, cred, vp, vp->v_label); + return (error); +} + +int +mac_vnode_check_signature(struct vnode *vp, unsigned char *sha1, + void * signature, size_t size) +{ + int error; + + if (!mac_vnode_enforce || !mac_proc_enforce) + return (0); + + MAC_CHECK(vnode_check_signature, vp, vp->v_label, sha1, signature, size); + return (error); +} + #if 0 int mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type) @@ -877,6 +943,21 @@ mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp) return (error); } +int +mac_vnode_check_searchfs(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist) +{ + kauth_cred_t cred; + int error; + + if (!mac_vnode_enforce || + !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + return (0); + + cred = vfs_context_ucred(ctx); + MAC_CHECK(vnode_check_searchfs, cred, vp, vp->v_label, alist); + return (error); +} + int mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which) { @@ -1058,14 +1139,59 @@ mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred, return (error); } +int +mac_vnode_check_uipc_bind(vfs_context_t ctx, struct vnode *dvp, + struct componentname *cnp, struct vnode_attr *vap) +{ + kauth_cred_t cred; + int error; + + if (!mac_vnode_enforce || + !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + return (0); + + cred = vfs_context_ucred(ctx); + MAC_CHECK(vnode_check_uipc_bind, cred, dvp, dvp->v_label, cnp, vap); + return (error); +} + +int +mac_vnode_check_uipc_connect(vfs_context_t ctx, struct vnode *vp) +{ + kauth_cred_t cred; + int error; + + if (!mac_vnode_enforce || + !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE)) + return (0); + + cred = vfs_context_ucred(ctx); + MAC_CHECK(vnode_check_uipc_connect, cred, vp, vp->v_label); + return (error); +} + void mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel) { kauth_cred_t cred = vfs_context_ucred(ctx); + struct label *tmpl = NULL; + + if (vp->v_label == NULL) + tmpl = mac_vnode_label_alloc(); vnode_lock(vp); + + /* recheck after lock */ + if (vp->v_label == NULL) { + vp->v_label = tmpl; + tmpl = NULL; + } + MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel); vnode_unlock(vp); + + if (tmpl != NULL) + mac_vnode_label_free(tmpl); } void @@ -1108,7 +1234,7 @@ mac_mount_label_associate(vfs_context_t ctx, struct mount *mp) } MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel); -#if MAC_DEBUG +#if DEBUG printf("MAC Framework enabling %s support: %s -> %s (%s)\n", mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel", mp->mnt_vfsstat.f_mntfromname, @@ -1273,7 +1399,7 @@ vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context) { int error; - if (!mac_vnode_enforce) + if (!mac_vnode_enforce || !mac_label_vnodes) return (0); if (vp->v_mount == NULL) {