#include <sys/vnode_internal.h>
#include <miscfs/devfs/devfsdefs.h>
-#include <miscfs/fdesc/fdesc.h>
+#include <miscfs/devfs/fdesc.h>
#include <security/mac_internal.h>
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
void
mac_mount_label_destroy(struct mount *mp)
{
-
-
if (mp->mnt_mntlabel != NULL) {
mac_mount_label_free(mp->mnt_mntlabel);
mp->mnt_mntlabel = NULL;
void
mac_vnode_label_free(struct label *label)
{
-
MAC_PERFORM(vnode_label_destroy, label);
mac_labelzone_free(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
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,
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);
+}
+
+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
{
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,
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;
}
void
-mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp,
- struct label *scriptvnodelabel, struct label *execl)
+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)
{
kauth_cred_t cred;
+ *disjoint = 0;
+ int error;
+ posix_cred_t pcred = posix_cred_get(new);
if (!mac_proc_enforce && !mac_vnode_enforce)
- return;
+ return;
/* 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);
+
+ /*
+ * 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;
+
+ error = 0;
+ 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);
+
+ error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp,
+ vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint),
+ 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_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);
+
+ error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp,
+ vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint),
+ error);
+ }
+ mac_policy_list_unbusy();
+ }
+ }
+ *labelupdateerror = error;
}
int
-mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp,
- struct label *scriptvnodelabel, struct label *execlabel, struct proc *p)
+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)
{
kauth_cred_t cred;
int result = 0;
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, offset, 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, offset, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
+ }
+ mac_policy_list_unbusy();
+ }
+ }
return (result);
}
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 = 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);
+ }
+ 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 = 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);
+ }
+ mac_policy_list_unbusy();
+ }
+ }
+
return (error);
}
int
-mac_vnode_check_signature(struct vnode *vp, unsigned char *sha1,
- void * signature, size_t size)
+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, off_t macho_offset,
+ unsigned char *sha1,
+ const void *signature, size_t size,
+ int flags, int *is_platform_binary)
{
int error;
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,
+ flags, is_platform_binary);
return (error);
}
}
int
-mac_vnode_check_rename_from(vfs_context_t ctx, struct vnode *dvp,
- struct vnode *vp, struct componentname *cnp)
+mac_vnode_check_rename(vfs_context_t ctx, struct vnode *dvp,
+ struct vnode *vp, struct componentname *cnp, struct vnode *tdvp,
+ struct vnode *tvp, struct componentname *tcnp)
{
kauth_cred_t cred;
int error;
- if (!mac_vnode_enforce ||
+ if (!mac_vnode_enforce ||
!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
return (0);
cred = vfs_context_ucred(ctx);
+
MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
vp->v_label, cnp);
+ if (error)
+ 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);
+
+ 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);
}
int
-mac_vnode_check_rename_to(vfs_context_t ctx, struct vnode *dvp,
- struct vnode *vp, int samedir, struct componentname *cnp)
+mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp)
{
kauth_cred_t cred;
int error;
return (0);
cred = vfs_context_ucred(ctx);
- MAC_CHECK(vnode_check_rename_to, cred, dvp, dvp->v_label, vp,
- vp != NULL ? vp->v_label : NULL, samedir, cnp);
+ MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
return (error);
}
int
-mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp)
+mac_vnode_check_searchfs(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist)
{
kauth_cred_t cred;
int error;
return (0);
cred = vfs_context_ucred(ctx);
- MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
+ MAC_CHECK(vnode_check_searchfs, cred, vp, vp->v_label, alist);
return (error);
}
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);
+}
+
+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_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,
{
int error;
- if (!mac_vnode_enforce)
+ if (!mac_vnode_enforce || !mac_label_vnodes)
return (0);
if (vp->v_mount == NULL) {
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;
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)))
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);
vp, vp->v_label);
socket_unlock(so, 1);
break;
+#endif
case DTYPE_PSXSHM:
pshm_label_associate(fp, vp, ctx);
break;