]> git.saurik.com Git - apple/xnu.git/blobdiff - security/mac_vfs.c
xnu-2422.1.72.tar.gz
[apple/xnu.git] / security / mac_vfs.c
index 7bf550622ad8488f2f85052bbb805d75f40807d2..cf54eafa9bce9430078ae17c540c304d27cec6e5 100644 (file)
@@ -405,6 +405,20 @@ mac_vnode_notify_open(vfs_context_t ctx, struct vnode *vp, int acc_flags)
        MAC_PERFORM(vnode_notify_open, cred, vp, vp->v_label, acc_flags);
 }
 
+void
+mac_vnode_notify_link(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_link, cred, dvp, dvp->v_label, vp, vp->v_label, cnp);
+}
+
 /*
  * Extended attribute 'name' was updated via
  * vn_setxattr() or vn_removexattr().  Allow the
@@ -449,7 +463,8 @@ mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp,
 
 int
 mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp,
-    struct label *scriptvnodelabel, struct label *execl)
+       struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execl,
+       void *macextensions)
 {
        kauth_cred_t cred;
        int disjoint = 0;
@@ -462,15 +477,58 @@ mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *
        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, &disjoint);
+
+       /*
+        * NB: Cannot use MAC_PERFORM macro because we need a sequence point after
+        *     calling exec_spawnattr_getmacpolicyinfo() and before passing the
+        *     spawnattrlen as an argument to the hook.
+        */
+       {
+               struct mac_policy_conf *mpc;
+               u_int i;
+
+               for (i = 0; i< mac_policy_list.staticmax; i++) {
+                       mpc = mac_policy_list.entries[i].mpc;
+                       if (mpc == NULL)
+                               continue;
+
+                       mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
+                       if (hook == NULL)
+                               continue;
+
+                       size_t spawnattrlen = 0;
+                       void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
+
+                       hook(cred, new, vfs_context_proc(ctx), vp, scriptvp, vp->v_label,
+                            scriptvnodelabel, execl, spawnattr, spawnattrlen, &disjoint);
+               }
+               if (mac_policy_list_conditional_busy() != 0) { 
+                       for (; i <= mac_policy_list.maxindex; i++) {
+                               mpc = mac_policy_list.entries[i].mpc;
+                               if (mpc == NULL)
+                                       continue;
+
+                               mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
+                               if (hook == NULL)
+                                       continue;
+
+                               size_t spawnattrlen = 0;
+                               void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
+
+                               hook(cred, new, vfs_context_proc(ctx), vp, scriptvp, vp->v_label,
+                                    scriptvnodelabel, execl, spawnattr, spawnattrlen, &disjoint);
+                       }
+                       mac_policy_list_unbusy();
+               }
+       }
 
        return (disjoint);
 }
 
 int
 mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp,
-    struct label *scriptvnodelabel, struct label *execlabel, struct proc *p)
+       struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execlabel,
+       struct proc *p, void *macextensions)
 {
        kauth_cred_t cred;
        int result = 0;
@@ -479,8 +537,48 @@ mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp,
                return result;
 
        cred = vfs_context_ucred(ctx);
-       MAC_BOOLEAN(cred_check_label_update_execve, ||, cred, vp, vp->v_label,
-                   scriptvnodelabel, execlabel, p);
+
+       /*
+        * NB: Cannot use MAC_BOOLEAN macro because we need a sequence point after
+        *     calling exec_spawnattr_getmacpolicyinfo() and before passing the
+        *     spawnattrlen as an argument to the hook.
+        */
+       {
+               struct mac_policy_conf *mpc;
+               u_int i;
+
+               for (i = 0; i< mac_policy_list.staticmax; i++) {
+                       mpc = mac_policy_list.entries[i].mpc;
+                       if (mpc == NULL)
+                               continue;
+
+                       mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
+                       if (hook == NULL)
+                               continue;
+
+                       size_t spawnattrlen = 0;
+                       void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
+
+                       result = result || hook(cred, vp, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
+               }
+               if (mac_policy_list_conditional_busy() != 0) { 
+                       for (; i <= mac_policy_list.maxindex; i++) {
+                               mpc = mac_policy_list.entries[i].mpc;
+                               if (mpc == NULL)
+                                       continue;
+
+                               mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
+                               if (hook == NULL)
+                                       continue;
+
+                               size_t spawnattrlen = 0;
+                               void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
+
+                               result = result || hook(cred, vp, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
+                       }
+                       mac_policy_list_unbusy();
+               }
+       }
 
        return (result);
 }
@@ -658,16 +756,65 @@ mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp,
     struct image_params *imgp)
 {
        kauth_cred_t cred;
-       int error;
+       int error = 0;
 
        if (!mac_vnode_enforce || !mac_proc_enforce)
                return (0);
 
        cred = vfs_context_ucred(ctx);
-       MAC_CHECK(vnode_check_exec, cred, vp, vp->v_label,
-                 (imgp != NULL) ? imgp->ip_execlabelp : NULL, 
-                 (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL,
-                 (imgp != NULL) ? &imgp->ip_csflags : NULL);
+
+       /*
+        * NB: Cannot use MAC_CHECK macro because we need a sequence point after
+        *     calling exec_spawnattr_getmacpolicyinfo() and before passing the
+        *     spawnattrlen as an argument to the hook.
+        */
+       {
+               struct mac_policy_conf *mpc;
+               u_int i;
+
+               for (i = 0; i< mac_policy_list.staticmax; i++) {
+                       mpc = mac_policy_list.entries[i].mpc;
+                       if (mpc == NULL)
+                               continue;
+
+                       mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
+                       if (hook == NULL)
+                               continue;
+
+                       size_t spawnattrlen = 0;
+                       void *spawnattr =  (imgp != NULL) ? exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen) : NULL;
+
+                       error = mac_error_select(
+                                       hook(cred, vp, vp->v_label,
+                                            (imgp != NULL) ? imgp->ip_execlabelp : NULL,
+                                            (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL,
+                                            (imgp != NULL) ? &imgp->ip_csflags : NULL,
+                                            spawnattr, spawnattrlen), error);
+               }
+               if (mac_policy_list_conditional_busy() != 0) { 
+                       for (; i <= mac_policy_list.maxindex; i++) {
+                               mpc = mac_policy_list.entries[i].mpc;
+                               if (mpc == NULL)
+                                       continue;
+
+                               mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
+                               if (hook == NULL)
+                                       continue;
+
+                               size_t spawnattrlen = 0;
+                               void *spawnattr =  (imgp != NULL) ? exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen) : NULL;
+
+                               error = mac_error_select(
+                                               hook(cred, vp, vp->v_label,
+                                                    (imgp != NULL) ? imgp->ip_execlabelp : NULL,
+                                                    (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL,
+                                                    (imgp != NULL) ? &imgp->ip_csflags : NULL,
+                                                    spawnattr, spawnattrlen), error);
+                       }
+                       mac_policy_list_unbusy();
+               }
+       }
+
        return (error);
 }
 
@@ -687,7 +834,8 @@ mac_vnode_check_fsgetpath(vfs_context_t ctx, struct vnode *vp)
 }
 
 int
-mac_vnode_check_signature(struct vnode *vp, unsigned char *sha1,
+mac_vnode_check_signature(struct vnode *vp, off_t macho_offset,
+                         unsigned char *sha1,
                          void * signature, size_t size)
 {
        int error;
@@ -695,7 +843,7 @@ mac_vnode_check_signature(struct vnode *vp, unsigned char *sha1,
        if (!mac_vnode_enforce || !mac_proc_enforce)
                return (0);
        
-       MAC_CHECK(vnode_check_signature, vp, vp->v_label, sha1, signature, size);
+       MAC_CHECK(vnode_check_signature, vp, vp->v_label, macho_offset, sha1, signature, size);
        return (error);
 }
 
@@ -1194,6 +1342,19 @@ mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlab
                mac_vnode_label_free(tmpl);
 }
 
+int
+mac_vnode_find_sigs(struct proc *p, struct vnode *vp, off_t offset)
+{
+       int error;
+
+       if (!mac_vnode_enforce || !mac_proc_enforce)
+               return (0);
+
+       MAC_CHECK(vnode_find_sigs, p, vp, offset, vp->v_label);
+
+       return (error);
+}
+
 void
 mac_mount_label_associate(vfs_context_t ctx, struct mount *mp)
 {
@@ -1446,7 +1607,9 @@ mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
     struct vnode *vp, vfs_context_t ctx)
 {
        struct fileproc *fp;
+#if CONFIG_MACF_SOCKET_SUBSET
        struct socket *so;
+#endif
        struct pipe *cpipe;
        struct vnode *fvp;
        struct proc *p;
@@ -1473,7 +1636,7 @@ mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
                goto out;
        }
 
-       switch (fp->f_fglob->fg_type) {
+       switch (FILEGLOB_DTYPE(fp->f_fglob)) {
        case DTYPE_VNODE:
                fvp = (struct vnode *)fp->f_fglob->fg_data;
                if ((error = vnode_getwithref(fvp)))
@@ -1481,6 +1644,7 @@ mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
                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;
                socket_lock(so, 1);
@@ -1489,6 +1653,7 @@ mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
                    vp, vp->v_label);
                socket_unlock(so, 1);
                break;
+#endif
        case DTYPE_PSXSHM:
                pshm_label_associate(fp, vp, ctx);
                break;