summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_mac.c135
-rw-r--r--sys/kern/subr_mbuf.c26
-rw-r--r--sys/kern/uipc_mbuf.c23
-rw-r--r--sys/kern/uipc_mbuf2.c23
-rw-r--r--sys/net/if_loop.c8
-rw-r--r--sys/security/mac/mac_framework.c135
-rw-r--r--sys/security/mac/mac_framework.h7
-rw-r--r--sys/security/mac/mac_internal.h135
-rw-r--r--sys/security/mac/mac_net.c135
-rw-r--r--sys/security/mac/mac_pipe.c135
-rw-r--r--sys/security/mac/mac_policy.h3
-rw-r--r--sys/security/mac/mac_process.c135
-rw-r--r--sys/security/mac/mac_syscalls.c135
-rw-r--r--sys/security/mac/mac_system.c135
-rw-r--r--sys/security/mac/mac_vfs.c135
-rw-r--r--sys/sys/mac.h7
-rw-r--r--sys/sys/mac_policy.h3
-rw-r--r--sys/sys/mbuf.h3
18 files changed, 1118 insertions, 200 deletions
diff --git a/sys/kern/kern_mac.c b/sys/kern/kern_mac.c
index ff4ca4f..2650874 100644
--- a/sys/kern/kern_mac.c
+++ b/sys/kern/kern_mac.c
@@ -120,6 +120,21 @@ static int mac_late = 0;
*/
static int ea_warn_once = 0;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+/*
+ * Flag to indicate whether or not we should allocate label storage for
+ * new mbufs. Since most dynamic policies we currently work with don't
+ * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
+ * unless specifically notified of interest. One result of this is
+ * that if a dynamically loaded policy requests mbuf labels, it must
+ * be able to deal with a NULL label being returned on any mbufs that
+ * were already in flight when the policy was loaded. Since the policy
+ * already has to deal with uninitialized labels, this probably won't
+ * be a problem. Note: currently no locking. Will this be a problem?
+ */
+static int mac_labelmbufs = 0;
+#endif
+
static int mac_enforce_fs = 1;
SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
&mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
@@ -281,6 +296,12 @@ static int mac_policy_list_busy;
&mac_policy_list_lock); \
} while (0)
+#define MAC_POLICY_LIST_ASSERT_EXCLUSIVE() do { \
+ mtx_assert(&mac_policy_list_lock, MA_OWNED); \
+ KASSERT(mac_policy_list_busy == 0, \
+ ("MAC_POLICY_LIST_ASSERT_EXCLUSIVE()")); \
+} while (0)
+
#define MAC_POLICY_LIST_BUSY() do { \
MAC_POLICY_LIST_LOCK(); \
mac_policy_list_busy++; \
@@ -464,6 +485,35 @@ mac_late_init(void)
}
/*
+ * After the policy list has changed, walk the list to update any global
+ * flags.
+ */
+static void
+mac_policy_updateflags(void)
+{
+ struct mac_policy_conf *tmpc;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ int labelmbufs;
+#endif
+
+ MAC_POLICY_LIST_ASSERT_EXCLUSIVE();
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ labelmbufs = 0;
+#endif
+ LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
+ labelmbufs++;
+#endif
+ }
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ mac_labelmbufs = (labelmbufs != 0);
+#endif
+}
+
+/*
* Allow MAC policy modules to register during boot, etc.
*/
int
@@ -530,6 +580,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
/* Per-policy initialization. */
if (mpc->mpc_ops->mpo_init != NULL)
(*(mpc->mpc_ops->mpo_init))(mpc);
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
@@ -574,7 +625,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
LIST_REMOVE(mpc, mpc_list);
mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
-
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
@@ -623,9 +674,11 @@ error_select(int error1, int error2)
static struct label *
mbuf_to_label(struct mbuf *mbuf)
{
+ struct m_tag *tag;
struct label *label;
- label = &mbuf->m_pkthdr.label;
+ tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
+ label = (struct label *)(tag+1);
return (label);
}
@@ -727,20 +780,20 @@ mac_init_ipq(struct ipq *ipq, int flag)
}
int
-mac_init_mbuf(struct mbuf *m, int flag)
+mac_init_mbuf_tag(struct m_tag *tag, int flag)
{
- int error;
-
- M_ASSERTPKTHDR(m);
+ struct label *label;
+ int error, trflag;
- mac_init_label(&m->m_pkthdr.label);
+ label = (struct label *) (tag + 1);
+ mac_init_label(label);
- MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
+ trflag = (flag == M_DONTWAIT ? M_NOWAIT : M_WAITOK);
+ MAC_CHECK(init_mbuf_label, label, trflag);
if (error) {
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
}
-
#ifdef MAC_DEBUG
if (error == 0)
atomic_add_int(&nmacmbufs, 1);
@@ -748,6 +801,37 @@ mac_init_mbuf(struct mbuf *m, int flag)
return (error);
}
+int
+mac_init_mbuf(struct mbuf *m, int flag)
+{
+ struct m_tag *tag;
+ int error;
+
+ M_ASSERTPKTHDR(m);
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ /*
+ * Don't reserve space for labels on mbufs unless we have a policy
+ * that uses the labels.
+ */
+ if (mac_labelmbufs) {
+#endif
+ tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
+ flag);
+ if (tag == NULL)
+ return (ENOMEM);
+ error = mac_init_mbuf_tag(tag, flag);
+ if (error) {
+ m_tag_free(tag);
+ return (error);
+ }
+ m_tag_prepend(m, tag);
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ }
+#endif
+ return (0);
+}
+
void
mac_init_mount(struct mount *mp)
{
@@ -935,11 +1019,14 @@ mac_destroy_ipq(struct ipq *ipq)
}
void
-mac_destroy_mbuf(struct mbuf *m)
+mac_destroy_mbuf_tag(struct m_tag *tag)
{
+ struct label *label;
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ label = (struct label *)(tag+1);
+
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
#ifdef MAC_DEBUG
atomic_subtract_int(&nmacmbufs, 1);
#endif
@@ -1033,6 +1120,21 @@ mac_destroy_vnode(struct vnode *vp)
mac_destroy_vnode_label(&vp->v_label);
}
+void
+mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
+{
+ struct label *src_label, *dest_label;
+
+ src_label = (struct label *)(src+1);
+ dest_label = (struct label *)(dest+1);
+
+ /*
+ * mac_init_mbuf_tag() is called on the target tag in
+ * m_tag_copy(), so we don't need to call it here.
+ */
+ MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
+}
+
static void
mac_copy_pipe_label(struct label *src, struct label *dest)
{
@@ -2318,13 +2420,12 @@ mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
struct label *label;
int error;
+ M_ASSERTPKTHDR(mbuf);
+
if (!mac_enforce_network)
return (0);
- M_ASSERTPKTHDR(mbuf);
label = mbuf_to_label(mbuf);
- if (!(label->l_flags & MAC_FLAG_INITIALIZED))
- if_printf(ifnet, "not initialized\n");
MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
label);
diff --git a/sys/kern/subr_mbuf.c b/sys/kern/subr_mbuf.c
index 123553b..ff226e7 100644
--- a/sys/kern/subr_mbuf.c
+++ b/sys/kern/subr_mbuf.c
@@ -1305,9 +1305,9 @@ m_gethdr(int how, short type)
if (mb != NULL) {
_mbhdr_setup(mb, type);
#ifdef MAC
- if (mac_init_mbuf(mb, how) != 0) {
+ if (mac_init_mbuf(mb, MBTOM(how)) != 0) {
m_free(mb);
- return NULL;
+ return (NULL);
}
#endif
}
@@ -1354,9 +1354,9 @@ m_gethdr_clrd(int how, short type)
if (mb != NULL) {
_mbhdr_setup(mb, type);
#ifdef MAC
- if (mac_init_mbuf(mb, how) != 0) {
+ if (mac_init_mbuf(mb, MBTOM(how)) != 0) {
m_free(mb);
- return NULL;
+ return (NULL);
}
#endif
bzero(mtod(mb, caddr_t), MHLEN);
@@ -1382,11 +1382,6 @@ m_free(struct mbuf *mb)
if ((mb->m_flags & M_PKTHDR) != 0)
m_tag_delete_chain(mb, NULL);
-#ifdef MAC
- if ((mb->m_flags & M_PKTHDR) &&
- (mb->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
- mac_destroy_mbuf(mb);
-#endif
nb = mb->m_next;
if ((mb->m_flags & M_EXT) != 0) {
MEXT_REM_REF(mb);
@@ -1429,11 +1424,6 @@ m_freem(struct mbuf *mb)
while (mb != NULL) {
if ((mb->m_flags & M_PKTHDR) != 0)
m_tag_delete_chain(mb, NULL);
-#ifdef MAC
- if ((mb->m_flags & M_PKTHDR) &&
- (mb->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
- mac_destroy_mbuf(mb);
-#endif
persist = 0;
m = mb;
mb = mb->m_next;
@@ -1501,9 +1491,11 @@ m_getcl(int how, short type, int flags)
_mext_init_ref(mb, &cl_refcntmap[cl2ref(mb->m_ext.ext_buf)]);
}
#ifdef MAC
- if ((flags & M_PKTHDR) && (mac_init_mbuf(mb, how) != 0)) {
- m_free(mb);
- return NULL;
+ if (flags & M_PKTHDR) {
+ if (mac_init_mbuf(mb, MBTOM(how)) != 0) {
+ m_free(mb);
+ return (NULL);
+ }
}
#endif
return (mb);
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 55d828d..08a7246 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -88,21 +88,21 @@ m_move_pkthdr(struct mbuf *to, struct mbuf *from)
#if 0
/* see below for why these are not enabled */
M_ASSERTPKTHDR(to);
+ /* Note: with MAC, this may not be a good assertion. */
KASSERT(SLIST_EMPTY(&to->m_pkthdr.tags),
("m_move_pkthdr: to has tags"));
#endif
KASSERT((to->m_flags & M_EXT) == 0, ("m_move_pkthdr: to has cluster"));
#ifdef MAC
+ /*
+ * XXXMAC: It could be this should also occur for non-MAC?
+ */
if (to->m_flags & M_PKTHDR)
- mac_destroy_mbuf(to);
+ m_tag_delete_chain(to, NULL);
#endif
to->m_flags = from->m_flags & M_COPYFLAGS;
to->m_data = to->m_pktdat;
to->m_pkthdr = from->m_pkthdr; /* especially tags */
-#ifdef MAC
- mac_init_mbuf(to, 1); /* XXXMAC no way to fail */
- mac_create_mbuf_from_mbuf(from, to);
-#endif
SLIST_INIT(&from->m_pkthdr.tags); /* purge tags from src */
from->m_flags &= ~M_PKTHDR;
}
@@ -125,20 +125,17 @@ m_dup_pkthdr(struct mbuf *to, struct mbuf *from, int how)
* assertions to trip. For now just disable them.
*/
M_ASSERTPKTHDR(to);
+ /* Note: with MAC, this may not be a good assertion. */
KASSERT(SLIST_EMPTY(&to->m_pkthdr.tags), ("m_dup_pkthdr: to has tags"));
#endif
#ifdef MAC
if (to->m_flags & M_PKTHDR)
- mac_destroy_mbuf(to);
+ m_tag_delete_chain(to, NULL);
#endif
to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT);
if ((to->m_flags & M_EXT) == 0)
to->m_data = to->m_pktdat;
to->m_pkthdr = from->m_pkthdr;
-#ifdef MAC
- mac_init_mbuf(to, 1); /* XXXMAC no way to fail */
- mac_create_mbuf_from_mbuf(from, to);
-#endif
SLIST_INIT(&to->m_pkthdr.tags);
return (m_tag_copy_chain(to, from, MBTOM(how)));
}
@@ -158,12 +155,8 @@ m_prepend(struct mbuf *m, int len, int how)
m_freem(m);
return (NULL);
}
- if (m->m_flags & M_PKTHDR) {
+ if (m->m_flags & M_PKTHDR)
M_MOVE_PKTHDR(mn, m);
-#ifdef MAC
- mac_destroy_mbuf(m);
-#endif
- }
mn->m_next = m;
m = mn;
if (len < MHLEN)
diff --git a/sys/kern/uipc_mbuf2.c b/sys/kern/uipc_mbuf2.c
index 50b37f5..000bb24 100644
--- a/sys/kern/uipc_mbuf2.c
+++ b/sys/kern/uipc_mbuf2.c
@@ -68,10 +68,13 @@
/*#define PULLDOWN_DEBUG*/
+#include "opt_mac.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/mac.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
@@ -327,6 +330,10 @@ m_tag_alloc(u_int32_t cookie, int type, int len, int wait)
void
m_tag_free(struct m_tag *t)
{
+#ifdef MAC
+ if (t->m_tag_id == PACKET_TAG_MACLABEL)
+ mac_destroy_mbuf_tag(t);
+#endif
free(t, M_PACKET_TAGS);
}
@@ -402,7 +409,21 @@ m_tag_copy(struct m_tag *t, int how)
p = m_tag_alloc(t->m_tag_cookie, t->m_tag_id, t->m_tag_len, how);
if (p == NULL)
return (NULL);
- bcopy(t + 1, p + 1, t->m_tag_len); /* Copy the data */
+#ifdef MAC
+ /*
+ * XXXMAC: we should probably pass off the initialization, and
+ * copying here? can we hide that PACKET_TAG_MACLABEL is
+ * special from the mbuf code?
+ */
+ if (t->m_tag_id == PACKET_TAG_MACLABEL) {
+ if (mac_init_mbuf_tag(p, how) != 0) {
+ m_tag_free(p);
+ return (NULL);
+ }
+ mac_copy_mbuf_tag(t, p);
+ } else
+#endif
+ bcopy(t + 1, p + 1, t->m_tag_len); /* Copy the data */
return p;
}
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index 09ba6a3..b78b146 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -214,14 +214,6 @@ looutput(ifp, m, dst, rt)
if (!n)
goto contiguousfail;
M_MOVE_PKTHDR(n, m);
-#ifdef MAC
- /*
- * XXXMAC: Once we put labels in tags and proper
- * primitives are used for relocating mbuf header
- * data, this will no longer be required.
- */
- m->m_pkthdr.label.l_flags &= ~MAC_FLAG_INITIALIZED;
-#endif
MCLGET(n, M_DONTWAIT);
if (! (n->m_flags & M_EXT)) {
m_freem(n);
diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c
index ff4ca4f..2650874 100644
--- a/sys/security/mac/mac_framework.c
+++ b/sys/security/mac/mac_framework.c
@@ -120,6 +120,21 @@ static int mac_late = 0;
*/
static int ea_warn_once = 0;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+/*
+ * Flag to indicate whether or not we should allocate label storage for
+ * new mbufs. Since most dynamic policies we currently work with don't
+ * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
+ * unless specifically notified of interest. One result of this is
+ * that if a dynamically loaded policy requests mbuf labels, it must
+ * be able to deal with a NULL label being returned on any mbufs that
+ * were already in flight when the policy was loaded. Since the policy
+ * already has to deal with uninitialized labels, this probably won't
+ * be a problem. Note: currently no locking. Will this be a problem?
+ */
+static int mac_labelmbufs = 0;
+#endif
+
static int mac_enforce_fs = 1;
SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
&mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
@@ -281,6 +296,12 @@ static int mac_policy_list_busy;
&mac_policy_list_lock); \
} while (0)
+#define MAC_POLICY_LIST_ASSERT_EXCLUSIVE() do { \
+ mtx_assert(&mac_policy_list_lock, MA_OWNED); \
+ KASSERT(mac_policy_list_busy == 0, \
+ ("MAC_POLICY_LIST_ASSERT_EXCLUSIVE()")); \
+} while (0)
+
#define MAC_POLICY_LIST_BUSY() do { \
MAC_POLICY_LIST_LOCK(); \
mac_policy_list_busy++; \
@@ -464,6 +485,35 @@ mac_late_init(void)
}
/*
+ * After the policy list has changed, walk the list to update any global
+ * flags.
+ */
+static void
+mac_policy_updateflags(void)
+{
+ struct mac_policy_conf *tmpc;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ int labelmbufs;
+#endif
+
+ MAC_POLICY_LIST_ASSERT_EXCLUSIVE();
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ labelmbufs = 0;
+#endif
+ LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
+ labelmbufs++;
+#endif
+ }
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ mac_labelmbufs = (labelmbufs != 0);
+#endif
+}
+
+/*
* Allow MAC policy modules to register during boot, etc.
*/
int
@@ -530,6 +580,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
/* Per-policy initialization. */
if (mpc->mpc_ops->mpo_init != NULL)
(*(mpc->mpc_ops->mpo_init))(mpc);
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
@@ -574,7 +625,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
LIST_REMOVE(mpc, mpc_list);
mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
-
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
@@ -623,9 +674,11 @@ error_select(int error1, int error2)
static struct label *
mbuf_to_label(struct mbuf *mbuf)
{
+ struct m_tag *tag;
struct label *label;
- label = &mbuf->m_pkthdr.label;
+ tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
+ label = (struct label *)(tag+1);
return (label);
}
@@ -727,20 +780,20 @@ mac_init_ipq(struct ipq *ipq, int flag)
}
int
-mac_init_mbuf(struct mbuf *m, int flag)
+mac_init_mbuf_tag(struct m_tag *tag, int flag)
{
- int error;
-
- M_ASSERTPKTHDR(m);
+ struct label *label;
+ int error, trflag;
- mac_init_label(&m->m_pkthdr.label);
+ label = (struct label *) (tag + 1);
+ mac_init_label(label);
- MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
+ trflag = (flag == M_DONTWAIT ? M_NOWAIT : M_WAITOK);
+ MAC_CHECK(init_mbuf_label, label, trflag);
if (error) {
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
}
-
#ifdef MAC_DEBUG
if (error == 0)
atomic_add_int(&nmacmbufs, 1);
@@ -748,6 +801,37 @@ mac_init_mbuf(struct mbuf *m, int flag)
return (error);
}
+int
+mac_init_mbuf(struct mbuf *m, int flag)
+{
+ struct m_tag *tag;
+ int error;
+
+ M_ASSERTPKTHDR(m);
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ /*
+ * Don't reserve space for labels on mbufs unless we have a policy
+ * that uses the labels.
+ */
+ if (mac_labelmbufs) {
+#endif
+ tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
+ flag);
+ if (tag == NULL)
+ return (ENOMEM);
+ error = mac_init_mbuf_tag(tag, flag);
+ if (error) {
+ m_tag_free(tag);
+ return (error);
+ }
+ m_tag_prepend(m, tag);
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ }
+#endif
+ return (0);
+}
+
void
mac_init_mount(struct mount *mp)
{
@@ -935,11 +1019,14 @@ mac_destroy_ipq(struct ipq *ipq)
}
void
-mac_destroy_mbuf(struct mbuf *m)
+mac_destroy_mbuf_tag(struct m_tag *tag)
{
+ struct label *label;
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ label = (struct label *)(tag+1);
+
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
#ifdef MAC_DEBUG
atomic_subtract_int(&nmacmbufs, 1);
#endif
@@ -1033,6 +1120,21 @@ mac_destroy_vnode(struct vnode *vp)
mac_destroy_vnode_label(&vp->v_label);
}
+void
+mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
+{
+ struct label *src_label, *dest_label;
+
+ src_label = (struct label *)(src+1);
+ dest_label = (struct label *)(dest+1);
+
+ /*
+ * mac_init_mbuf_tag() is called on the target tag in
+ * m_tag_copy(), so we don't need to call it here.
+ */
+ MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
+}
+
static void
mac_copy_pipe_label(struct label *src, struct label *dest)
{
@@ -2318,13 +2420,12 @@ mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
struct label *label;
int error;
+ M_ASSERTPKTHDR(mbuf);
+
if (!mac_enforce_network)
return (0);
- M_ASSERTPKTHDR(mbuf);
label = mbuf_to_label(mbuf);
- if (!(label->l_flags & MAC_FLAG_INITIALIZED))
- if_printf(ifnet, "not initialized\n");
MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
label);
diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h
index 3cc856d..77c33c4 100644
--- a/sys/security/mac/mac_framework.h
+++ b/sys/security/mac/mac_framework.h
@@ -109,6 +109,7 @@ struct ifnet;
struct ifreq;
struct image_params;
struct ipq;
+struct m_tag;
struct mbuf;
struct mount;
struct proc;
@@ -136,11 +137,13 @@ void mac_init_ifnet(struct ifnet *);
int mac_init_ipq(struct ipq *, int flag);
int mac_init_socket(struct socket *, int flag);
void mac_init_pipe(struct pipe *);
-int mac_init_mbuf(struct mbuf *m, int flag);
+int mac_init_mbuf(struct mbuf *mbuf, int flag);
+int mac_init_mbuf_tag(struct m_tag *, int flag);
void mac_init_mount(struct mount *);
void mac_init_proc(struct proc *);
void mac_init_vnode(struct vnode *);
void mac_init_vnode_label(struct label *);
+void mac_copy_mbuf_tag(struct m_tag *, struct m_tag *);
void mac_copy_vnode_label(struct label *, struct label *label);
void mac_destroy_bpfdesc(struct bpf_d *);
void mac_destroy_cred(struct ucred *);
@@ -150,7 +153,7 @@ void mac_destroy_ipq(struct ipq *);
void mac_destroy_socket(struct socket *);
void mac_destroy_pipe(struct pipe *);
void mac_destroy_proc(struct proc *);
-void mac_destroy_mbuf(struct mbuf *);
+void mac_destroy_mbuf_tag(struct m_tag *);
void mac_destroy_mount(struct mount *);
void mac_destroy_vnode(struct vnode *);
void mac_destroy_vnode_label(struct label *);
diff --git a/sys/security/mac/mac_internal.h b/sys/security/mac/mac_internal.h
index ff4ca4f..2650874 100644
--- a/sys/security/mac/mac_internal.h
+++ b/sys/security/mac/mac_internal.h
@@ -120,6 +120,21 @@ static int mac_late = 0;
*/
static int ea_warn_once = 0;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+/*
+ * Flag to indicate whether or not we should allocate label storage for
+ * new mbufs. Since most dynamic policies we currently work with don't
+ * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
+ * unless specifically notified of interest. One result of this is
+ * that if a dynamically loaded policy requests mbuf labels, it must
+ * be able to deal with a NULL label being returned on any mbufs that
+ * were already in flight when the policy was loaded. Since the policy
+ * already has to deal with uninitialized labels, this probably won't
+ * be a problem. Note: currently no locking. Will this be a problem?
+ */
+static int mac_labelmbufs = 0;
+#endif
+
static int mac_enforce_fs = 1;
SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
&mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
@@ -281,6 +296,12 @@ static int mac_policy_list_busy;
&mac_policy_list_lock); \
} while (0)
+#define MAC_POLICY_LIST_ASSERT_EXCLUSIVE() do { \
+ mtx_assert(&mac_policy_list_lock, MA_OWNED); \
+ KASSERT(mac_policy_list_busy == 0, \
+ ("MAC_POLICY_LIST_ASSERT_EXCLUSIVE()")); \
+} while (0)
+
#define MAC_POLICY_LIST_BUSY() do { \
MAC_POLICY_LIST_LOCK(); \
mac_policy_list_busy++; \
@@ -464,6 +485,35 @@ mac_late_init(void)
}
/*
+ * After the policy list has changed, walk the list to update any global
+ * flags.
+ */
+static void
+mac_policy_updateflags(void)
+{
+ struct mac_policy_conf *tmpc;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ int labelmbufs;
+#endif
+
+ MAC_POLICY_LIST_ASSERT_EXCLUSIVE();
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ labelmbufs = 0;
+#endif
+ LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
+ labelmbufs++;
+#endif
+ }
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ mac_labelmbufs = (labelmbufs != 0);
+#endif
+}
+
+/*
* Allow MAC policy modules to register during boot, etc.
*/
int
@@ -530,6 +580,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
/* Per-policy initialization. */
if (mpc->mpc_ops->mpo_init != NULL)
(*(mpc->mpc_ops->mpo_init))(mpc);
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
@@ -574,7 +625,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
LIST_REMOVE(mpc, mpc_list);
mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
-
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
@@ -623,9 +674,11 @@ error_select(int error1, int error2)
static struct label *
mbuf_to_label(struct mbuf *mbuf)
{
+ struct m_tag *tag;
struct label *label;
- label = &mbuf->m_pkthdr.label;
+ tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
+ label = (struct label *)(tag+1);
return (label);
}
@@ -727,20 +780,20 @@ mac_init_ipq(struct ipq *ipq, int flag)
}
int
-mac_init_mbuf(struct mbuf *m, int flag)
+mac_init_mbuf_tag(struct m_tag *tag, int flag)
{
- int error;
-
- M_ASSERTPKTHDR(m);
+ struct label *label;
+ int error, trflag;
- mac_init_label(&m->m_pkthdr.label);
+ label = (struct label *) (tag + 1);
+ mac_init_label(label);
- MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
+ trflag = (flag == M_DONTWAIT ? M_NOWAIT : M_WAITOK);
+ MAC_CHECK(init_mbuf_label, label, trflag);
if (error) {
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
}
-
#ifdef MAC_DEBUG
if (error == 0)
atomic_add_int(&nmacmbufs, 1);
@@ -748,6 +801,37 @@ mac_init_mbuf(struct mbuf *m, int flag)
return (error);
}
+int
+mac_init_mbuf(struct mbuf *m, int flag)
+{
+ struct m_tag *tag;
+ int error;
+
+ M_ASSERTPKTHDR(m);
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ /*
+ * Don't reserve space for labels on mbufs unless we have a policy
+ * that uses the labels.
+ */
+ if (mac_labelmbufs) {
+#endif
+ tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
+ flag);
+ if (tag == NULL)
+ return (ENOMEM);
+ error = mac_init_mbuf_tag(tag, flag);
+ if (error) {
+ m_tag_free(tag);
+ return (error);
+ }
+ m_tag_prepend(m, tag);
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ }
+#endif
+ return (0);
+}
+
void
mac_init_mount(struct mount *mp)
{
@@ -935,11 +1019,14 @@ mac_destroy_ipq(struct ipq *ipq)
}
void
-mac_destroy_mbuf(struct mbuf *m)
+mac_destroy_mbuf_tag(struct m_tag *tag)
{
+ struct label *label;
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ label = (struct label *)(tag+1);
+
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
#ifdef MAC_DEBUG
atomic_subtract_int(&nmacmbufs, 1);
#endif
@@ -1033,6 +1120,21 @@ mac_destroy_vnode(struct vnode *vp)
mac_destroy_vnode_label(&vp->v_label);
}
+void
+mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
+{
+ struct label *src_label, *dest_label;
+
+ src_label = (struct label *)(src+1);
+ dest_label = (struct label *)(dest+1);
+
+ /*
+ * mac_init_mbuf_tag() is called on the target tag in
+ * m_tag_copy(), so we don't need to call it here.
+ */
+ MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
+}
+
static void
mac_copy_pipe_label(struct label *src, struct label *dest)
{
@@ -2318,13 +2420,12 @@ mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
struct label *label;
int error;
+ M_ASSERTPKTHDR(mbuf);
+
if (!mac_enforce_network)
return (0);
- M_ASSERTPKTHDR(mbuf);
label = mbuf_to_label(mbuf);
- if (!(label->l_flags & MAC_FLAG_INITIALIZED))
- if_printf(ifnet, "not initialized\n");
MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
label);
diff --git a/sys/security/mac/mac_net.c b/sys/security/mac/mac_net.c
index ff4ca4f..2650874 100644
--- a/sys/security/mac/mac_net.c
+++ b/sys/security/mac/mac_net.c
@@ -120,6 +120,21 @@ static int mac_late = 0;
*/
static int ea_warn_once = 0;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+/*
+ * Flag to indicate whether or not we should allocate label storage for
+ * new mbufs. Since most dynamic policies we currently work with don't
+ * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
+ * unless specifically notified of interest. One result of this is
+ * that if a dynamically loaded policy requests mbuf labels, it must
+ * be able to deal with a NULL label being returned on any mbufs that
+ * were already in flight when the policy was loaded. Since the policy
+ * already has to deal with uninitialized labels, this probably won't
+ * be a problem. Note: currently no locking. Will this be a problem?
+ */
+static int mac_labelmbufs = 0;
+#endif
+
static int mac_enforce_fs = 1;
SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
&mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
@@ -281,6 +296,12 @@ static int mac_policy_list_busy;
&mac_policy_list_lock); \
} while (0)
+#define MAC_POLICY_LIST_ASSERT_EXCLUSIVE() do { \
+ mtx_assert(&mac_policy_list_lock, MA_OWNED); \
+ KASSERT(mac_policy_list_busy == 0, \
+ ("MAC_POLICY_LIST_ASSERT_EXCLUSIVE()")); \
+} while (0)
+
#define MAC_POLICY_LIST_BUSY() do { \
MAC_POLICY_LIST_LOCK(); \
mac_policy_list_busy++; \
@@ -464,6 +485,35 @@ mac_late_init(void)
}
/*
+ * After the policy list has changed, walk the list to update any global
+ * flags.
+ */
+static void
+mac_policy_updateflags(void)
+{
+ struct mac_policy_conf *tmpc;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ int labelmbufs;
+#endif
+
+ MAC_POLICY_LIST_ASSERT_EXCLUSIVE();
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ labelmbufs = 0;
+#endif
+ LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
+ labelmbufs++;
+#endif
+ }
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ mac_labelmbufs = (labelmbufs != 0);
+#endif
+}
+
+/*
* Allow MAC policy modules to register during boot, etc.
*/
int
@@ -530,6 +580,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
/* Per-policy initialization. */
if (mpc->mpc_ops->mpo_init != NULL)
(*(mpc->mpc_ops->mpo_init))(mpc);
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
@@ -574,7 +625,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
LIST_REMOVE(mpc, mpc_list);
mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
-
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
@@ -623,9 +674,11 @@ error_select(int error1, int error2)
static struct label *
mbuf_to_label(struct mbuf *mbuf)
{
+ struct m_tag *tag;
struct label *label;
- label = &mbuf->m_pkthdr.label;
+ tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
+ label = (struct label *)(tag+1);
return (label);
}
@@ -727,20 +780,20 @@ mac_init_ipq(struct ipq *ipq, int flag)
}
int
-mac_init_mbuf(struct mbuf *m, int flag)
+mac_init_mbuf_tag(struct m_tag *tag, int flag)
{
- int error;
-
- M_ASSERTPKTHDR(m);
+ struct label *label;
+ int error, trflag;
- mac_init_label(&m->m_pkthdr.label);
+ label = (struct label *) (tag + 1);
+ mac_init_label(label);
- MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
+ trflag = (flag == M_DONTWAIT ? M_NOWAIT : M_WAITOK);
+ MAC_CHECK(init_mbuf_label, label, trflag);
if (error) {
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
}
-
#ifdef MAC_DEBUG
if (error == 0)
atomic_add_int(&nmacmbufs, 1);
@@ -748,6 +801,37 @@ mac_init_mbuf(struct mbuf *m, int flag)
return (error);
}
+int
+mac_init_mbuf(struct mbuf *m, int flag)
+{
+ struct m_tag *tag;
+ int error;
+
+ M_ASSERTPKTHDR(m);
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ /*
+ * Don't reserve space for labels on mbufs unless we have a policy
+ * that uses the labels.
+ */
+ if (mac_labelmbufs) {
+#endif
+ tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
+ flag);
+ if (tag == NULL)
+ return (ENOMEM);
+ error = mac_init_mbuf_tag(tag, flag);
+ if (error) {
+ m_tag_free(tag);
+ return (error);
+ }
+ m_tag_prepend(m, tag);
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ }
+#endif
+ return (0);
+}
+
void
mac_init_mount(struct mount *mp)
{
@@ -935,11 +1019,14 @@ mac_destroy_ipq(struct ipq *ipq)
}
void
-mac_destroy_mbuf(struct mbuf *m)
+mac_destroy_mbuf_tag(struct m_tag *tag)
{
+ struct label *label;
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ label = (struct label *)(tag+1);
+
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
#ifdef MAC_DEBUG
atomic_subtract_int(&nmacmbufs, 1);
#endif
@@ -1033,6 +1120,21 @@ mac_destroy_vnode(struct vnode *vp)
mac_destroy_vnode_label(&vp->v_label);
}
+void
+mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
+{
+ struct label *src_label, *dest_label;
+
+ src_label = (struct label *)(src+1);
+ dest_label = (struct label *)(dest+1);
+
+ /*
+ * mac_init_mbuf_tag() is called on the target tag in
+ * m_tag_copy(), so we don't need to call it here.
+ */
+ MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
+}
+
static void
mac_copy_pipe_label(struct label *src, struct label *dest)
{
@@ -2318,13 +2420,12 @@ mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
struct label *label;
int error;
+ M_ASSERTPKTHDR(mbuf);
+
if (!mac_enforce_network)
return (0);
- M_ASSERTPKTHDR(mbuf);
label = mbuf_to_label(mbuf);
- if (!(label->l_flags & MAC_FLAG_INITIALIZED))
- if_printf(ifnet, "not initialized\n");
MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
label);
diff --git a/sys/security/mac/mac_pipe.c b/sys/security/mac/mac_pipe.c
index ff4ca4f..2650874 100644
--- a/sys/security/mac/mac_pipe.c
+++ b/sys/security/mac/mac_pipe.c
@@ -120,6 +120,21 @@ static int mac_late = 0;
*/
static int ea_warn_once = 0;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+/*
+ * Flag to indicate whether or not we should allocate label storage for
+ * new mbufs. Since most dynamic policies we currently work with don't
+ * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
+ * unless specifically notified of interest. One result of this is
+ * that if a dynamically loaded policy requests mbuf labels, it must
+ * be able to deal with a NULL label being returned on any mbufs that
+ * were already in flight when the policy was loaded. Since the policy
+ * already has to deal with uninitialized labels, this probably won't
+ * be a problem. Note: currently no locking. Will this be a problem?
+ */
+static int mac_labelmbufs = 0;
+#endif
+
static int mac_enforce_fs = 1;
SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
&mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
@@ -281,6 +296,12 @@ static int mac_policy_list_busy;
&mac_policy_list_lock); \
} while (0)
+#define MAC_POLICY_LIST_ASSERT_EXCLUSIVE() do { \
+ mtx_assert(&mac_policy_list_lock, MA_OWNED); \
+ KASSERT(mac_policy_list_busy == 0, \
+ ("MAC_POLICY_LIST_ASSERT_EXCLUSIVE()")); \
+} while (0)
+
#define MAC_POLICY_LIST_BUSY() do { \
MAC_POLICY_LIST_LOCK(); \
mac_policy_list_busy++; \
@@ -464,6 +485,35 @@ mac_late_init(void)
}
/*
+ * After the policy list has changed, walk the list to update any global
+ * flags.
+ */
+static void
+mac_policy_updateflags(void)
+{
+ struct mac_policy_conf *tmpc;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ int labelmbufs;
+#endif
+
+ MAC_POLICY_LIST_ASSERT_EXCLUSIVE();
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ labelmbufs = 0;
+#endif
+ LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
+ labelmbufs++;
+#endif
+ }
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ mac_labelmbufs = (labelmbufs != 0);
+#endif
+}
+
+/*
* Allow MAC policy modules to register during boot, etc.
*/
int
@@ -530,6 +580,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
/* Per-policy initialization. */
if (mpc->mpc_ops->mpo_init != NULL)
(*(mpc->mpc_ops->mpo_init))(mpc);
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
@@ -574,7 +625,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
LIST_REMOVE(mpc, mpc_list);
mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
-
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
@@ -623,9 +674,11 @@ error_select(int error1, int error2)
static struct label *
mbuf_to_label(struct mbuf *mbuf)
{
+ struct m_tag *tag;
struct label *label;
- label = &mbuf->m_pkthdr.label;
+ tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
+ label = (struct label *)(tag+1);
return (label);
}
@@ -727,20 +780,20 @@ mac_init_ipq(struct ipq *ipq, int flag)
}
int
-mac_init_mbuf(struct mbuf *m, int flag)
+mac_init_mbuf_tag(struct m_tag *tag, int flag)
{
- int error;
-
- M_ASSERTPKTHDR(m);
+ struct label *label;
+ int error, trflag;
- mac_init_label(&m->m_pkthdr.label);
+ label = (struct label *) (tag + 1);
+ mac_init_label(label);
- MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
+ trflag = (flag == M_DONTWAIT ? M_NOWAIT : M_WAITOK);
+ MAC_CHECK(init_mbuf_label, label, trflag);
if (error) {
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
}
-
#ifdef MAC_DEBUG
if (error == 0)
atomic_add_int(&nmacmbufs, 1);
@@ -748,6 +801,37 @@ mac_init_mbuf(struct mbuf *m, int flag)
return (error);
}
+int
+mac_init_mbuf(struct mbuf *m, int flag)
+{
+ struct m_tag *tag;
+ int error;
+
+ M_ASSERTPKTHDR(m);
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ /*
+ * Don't reserve space for labels on mbufs unless we have a policy
+ * that uses the labels.
+ */
+ if (mac_labelmbufs) {
+#endif
+ tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
+ flag);
+ if (tag == NULL)
+ return (ENOMEM);
+ error = mac_init_mbuf_tag(tag, flag);
+ if (error) {
+ m_tag_free(tag);
+ return (error);
+ }
+ m_tag_prepend(m, tag);
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ }
+#endif
+ return (0);
+}
+
void
mac_init_mount(struct mount *mp)
{
@@ -935,11 +1019,14 @@ mac_destroy_ipq(struct ipq *ipq)
}
void
-mac_destroy_mbuf(struct mbuf *m)
+mac_destroy_mbuf_tag(struct m_tag *tag)
{
+ struct label *label;
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ label = (struct label *)(tag+1);
+
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
#ifdef MAC_DEBUG
atomic_subtract_int(&nmacmbufs, 1);
#endif
@@ -1033,6 +1120,21 @@ mac_destroy_vnode(struct vnode *vp)
mac_destroy_vnode_label(&vp->v_label);
}
+void
+mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
+{
+ struct label *src_label, *dest_label;
+
+ src_label = (struct label *)(src+1);
+ dest_label = (struct label *)(dest+1);
+
+ /*
+ * mac_init_mbuf_tag() is called on the target tag in
+ * m_tag_copy(), so we don't need to call it here.
+ */
+ MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
+}
+
static void
mac_copy_pipe_label(struct label *src, struct label *dest)
{
@@ -2318,13 +2420,12 @@ mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
struct label *label;
int error;
+ M_ASSERTPKTHDR(mbuf);
+
if (!mac_enforce_network)
return (0);
- M_ASSERTPKTHDR(mbuf);
label = mbuf_to_label(mbuf);
- if (!(label->l_flags & MAC_FLAG_INITIALIZED))
- if_printf(ifnet, "not initialized\n");
MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
label);
diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h
index 4e00577..e3d649e 100644
--- a/sys/security/mac/mac_policy.h
+++ b/sys/security/mac/mac_policy.h
@@ -95,6 +95,8 @@ struct mac_policy_ops {
void (*mpo_destroy_pipe_label)(struct label *label);
void (*mpo_destroy_proc_label)(struct label *label);
void (*mpo_destroy_vnode_label)(struct label *label);
+ void (*mpo_copy_mbuf_label)(struct label *src,
+ struct label *dest);
void (*mpo_copy_pipe_label)(struct label *src,
struct label *dest);
void (*mpo_copy_vnode_label)(struct label *src,
@@ -431,6 +433,7 @@ struct mac_policy_conf {
/* Flags for the mpc_loadtime_flags field. */
#define MPC_LOADTIME_FLAG_NOTLATE 0x00000001
#define MPC_LOADTIME_FLAG_UNLOADOK 0x00000002
+#define MPC_LOADTIME_FLAG_LABELMBUFS 0x00000004
/* Flags for the mpc_runtime_flags field. */
#define MPC_RUNTIME_FLAG_REGISTERED 0x00000001
diff --git a/sys/security/mac/mac_process.c b/sys/security/mac/mac_process.c
index ff4ca4f..2650874 100644
--- a/sys/security/mac/mac_process.c
+++ b/sys/security/mac/mac_process.c
@@ -120,6 +120,21 @@ static int mac_late = 0;
*/
static int ea_warn_once = 0;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+/*
+ * Flag to indicate whether or not we should allocate label storage for
+ * new mbufs. Since most dynamic policies we currently work with don't
+ * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
+ * unless specifically notified of interest. One result of this is
+ * that if a dynamically loaded policy requests mbuf labels, it must
+ * be able to deal with a NULL label being returned on any mbufs that
+ * were already in flight when the policy was loaded. Since the policy
+ * already has to deal with uninitialized labels, this probably won't
+ * be a problem. Note: currently no locking. Will this be a problem?
+ */
+static int mac_labelmbufs = 0;
+#endif
+
static int mac_enforce_fs = 1;
SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
&mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
@@ -281,6 +296,12 @@ static int mac_policy_list_busy;
&mac_policy_list_lock); \
} while (0)
+#define MAC_POLICY_LIST_ASSERT_EXCLUSIVE() do { \
+ mtx_assert(&mac_policy_list_lock, MA_OWNED); \
+ KASSERT(mac_policy_list_busy == 0, \
+ ("MAC_POLICY_LIST_ASSERT_EXCLUSIVE()")); \
+} while (0)
+
#define MAC_POLICY_LIST_BUSY() do { \
MAC_POLICY_LIST_LOCK(); \
mac_policy_list_busy++; \
@@ -464,6 +485,35 @@ mac_late_init(void)
}
/*
+ * After the policy list has changed, walk the list to update any global
+ * flags.
+ */
+static void
+mac_policy_updateflags(void)
+{
+ struct mac_policy_conf *tmpc;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ int labelmbufs;
+#endif
+
+ MAC_POLICY_LIST_ASSERT_EXCLUSIVE();
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ labelmbufs = 0;
+#endif
+ LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
+ labelmbufs++;
+#endif
+ }
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ mac_labelmbufs = (labelmbufs != 0);
+#endif
+}
+
+/*
* Allow MAC policy modules to register during boot, etc.
*/
int
@@ -530,6 +580,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
/* Per-policy initialization. */
if (mpc->mpc_ops->mpo_init != NULL)
(*(mpc->mpc_ops->mpo_init))(mpc);
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
@@ -574,7 +625,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
LIST_REMOVE(mpc, mpc_list);
mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
-
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
@@ -623,9 +674,11 @@ error_select(int error1, int error2)
static struct label *
mbuf_to_label(struct mbuf *mbuf)
{
+ struct m_tag *tag;
struct label *label;
- label = &mbuf->m_pkthdr.label;
+ tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
+ label = (struct label *)(tag+1);
return (label);
}
@@ -727,20 +780,20 @@ mac_init_ipq(struct ipq *ipq, int flag)
}
int
-mac_init_mbuf(struct mbuf *m, int flag)
+mac_init_mbuf_tag(struct m_tag *tag, int flag)
{
- int error;
-
- M_ASSERTPKTHDR(m);
+ struct label *label;
+ int error, trflag;
- mac_init_label(&m->m_pkthdr.label);
+ label = (struct label *) (tag + 1);
+ mac_init_label(label);
- MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
+ trflag = (flag == M_DONTWAIT ? M_NOWAIT : M_WAITOK);
+ MAC_CHECK(init_mbuf_label, label, trflag);
if (error) {
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
}
-
#ifdef MAC_DEBUG
if (error == 0)
atomic_add_int(&nmacmbufs, 1);
@@ -748,6 +801,37 @@ mac_init_mbuf(struct mbuf *m, int flag)
return (error);
}
+int
+mac_init_mbuf(struct mbuf *m, int flag)
+{
+ struct m_tag *tag;
+ int error;
+
+ M_ASSERTPKTHDR(m);
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ /*
+ * Don't reserve space for labels on mbufs unless we have a policy
+ * that uses the labels.
+ */
+ if (mac_labelmbufs) {
+#endif
+ tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
+ flag);
+ if (tag == NULL)
+ return (ENOMEM);
+ error = mac_init_mbuf_tag(tag, flag);
+ if (error) {
+ m_tag_free(tag);
+ return (error);
+ }
+ m_tag_prepend(m, tag);
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ }
+#endif
+ return (0);
+}
+
void
mac_init_mount(struct mount *mp)
{
@@ -935,11 +1019,14 @@ mac_destroy_ipq(struct ipq *ipq)
}
void
-mac_destroy_mbuf(struct mbuf *m)
+mac_destroy_mbuf_tag(struct m_tag *tag)
{
+ struct label *label;
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ label = (struct label *)(tag+1);
+
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
#ifdef MAC_DEBUG
atomic_subtract_int(&nmacmbufs, 1);
#endif
@@ -1033,6 +1120,21 @@ mac_destroy_vnode(struct vnode *vp)
mac_destroy_vnode_label(&vp->v_label);
}
+void
+mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
+{
+ struct label *src_label, *dest_label;
+
+ src_label = (struct label *)(src+1);
+ dest_label = (struct label *)(dest+1);
+
+ /*
+ * mac_init_mbuf_tag() is called on the target tag in
+ * m_tag_copy(), so we don't need to call it here.
+ */
+ MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
+}
+
static void
mac_copy_pipe_label(struct label *src, struct label *dest)
{
@@ -2318,13 +2420,12 @@ mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
struct label *label;
int error;
+ M_ASSERTPKTHDR(mbuf);
+
if (!mac_enforce_network)
return (0);
- M_ASSERTPKTHDR(mbuf);
label = mbuf_to_label(mbuf);
- if (!(label->l_flags & MAC_FLAG_INITIALIZED))
- if_printf(ifnet, "not initialized\n");
MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
label);
diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c
index ff4ca4f..2650874 100644
--- a/sys/security/mac/mac_syscalls.c
+++ b/sys/security/mac/mac_syscalls.c
@@ -120,6 +120,21 @@ static int mac_late = 0;
*/
static int ea_warn_once = 0;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+/*
+ * Flag to indicate whether or not we should allocate label storage for
+ * new mbufs. Since most dynamic policies we currently work with don't
+ * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
+ * unless specifically notified of interest. One result of this is
+ * that if a dynamically loaded policy requests mbuf labels, it must
+ * be able to deal with a NULL label being returned on any mbufs that
+ * were already in flight when the policy was loaded. Since the policy
+ * already has to deal with uninitialized labels, this probably won't
+ * be a problem. Note: currently no locking. Will this be a problem?
+ */
+static int mac_labelmbufs = 0;
+#endif
+
static int mac_enforce_fs = 1;
SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
&mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
@@ -281,6 +296,12 @@ static int mac_policy_list_busy;
&mac_policy_list_lock); \
} while (0)
+#define MAC_POLICY_LIST_ASSERT_EXCLUSIVE() do { \
+ mtx_assert(&mac_policy_list_lock, MA_OWNED); \
+ KASSERT(mac_policy_list_busy == 0, \
+ ("MAC_POLICY_LIST_ASSERT_EXCLUSIVE()")); \
+} while (0)
+
#define MAC_POLICY_LIST_BUSY() do { \
MAC_POLICY_LIST_LOCK(); \
mac_policy_list_busy++; \
@@ -464,6 +485,35 @@ mac_late_init(void)
}
/*
+ * After the policy list has changed, walk the list to update any global
+ * flags.
+ */
+static void
+mac_policy_updateflags(void)
+{
+ struct mac_policy_conf *tmpc;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ int labelmbufs;
+#endif
+
+ MAC_POLICY_LIST_ASSERT_EXCLUSIVE();
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ labelmbufs = 0;
+#endif
+ LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
+ labelmbufs++;
+#endif
+ }
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ mac_labelmbufs = (labelmbufs != 0);
+#endif
+}
+
+/*
* Allow MAC policy modules to register during boot, etc.
*/
int
@@ -530,6 +580,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
/* Per-policy initialization. */
if (mpc->mpc_ops->mpo_init != NULL)
(*(mpc->mpc_ops->mpo_init))(mpc);
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
@@ -574,7 +625,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
LIST_REMOVE(mpc, mpc_list);
mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
-
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
@@ -623,9 +674,11 @@ error_select(int error1, int error2)
static struct label *
mbuf_to_label(struct mbuf *mbuf)
{
+ struct m_tag *tag;
struct label *label;
- label = &mbuf->m_pkthdr.label;
+ tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
+ label = (struct label *)(tag+1);
return (label);
}
@@ -727,20 +780,20 @@ mac_init_ipq(struct ipq *ipq, int flag)
}
int
-mac_init_mbuf(struct mbuf *m, int flag)
+mac_init_mbuf_tag(struct m_tag *tag, int flag)
{
- int error;
-
- M_ASSERTPKTHDR(m);
+ struct label *label;
+ int error, trflag;
- mac_init_label(&m->m_pkthdr.label);
+ label = (struct label *) (tag + 1);
+ mac_init_label(label);
- MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
+ trflag = (flag == M_DONTWAIT ? M_NOWAIT : M_WAITOK);
+ MAC_CHECK(init_mbuf_label, label, trflag);
if (error) {
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
}
-
#ifdef MAC_DEBUG
if (error == 0)
atomic_add_int(&nmacmbufs, 1);
@@ -748,6 +801,37 @@ mac_init_mbuf(struct mbuf *m, int flag)
return (error);
}
+int
+mac_init_mbuf(struct mbuf *m, int flag)
+{
+ struct m_tag *tag;
+ int error;
+
+ M_ASSERTPKTHDR(m);
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ /*
+ * Don't reserve space for labels on mbufs unless we have a policy
+ * that uses the labels.
+ */
+ if (mac_labelmbufs) {
+#endif
+ tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
+ flag);
+ if (tag == NULL)
+ return (ENOMEM);
+ error = mac_init_mbuf_tag(tag, flag);
+ if (error) {
+ m_tag_free(tag);
+ return (error);
+ }
+ m_tag_prepend(m, tag);
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ }
+#endif
+ return (0);
+}
+
void
mac_init_mount(struct mount *mp)
{
@@ -935,11 +1019,14 @@ mac_destroy_ipq(struct ipq *ipq)
}
void
-mac_destroy_mbuf(struct mbuf *m)
+mac_destroy_mbuf_tag(struct m_tag *tag)
{
+ struct label *label;
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ label = (struct label *)(tag+1);
+
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
#ifdef MAC_DEBUG
atomic_subtract_int(&nmacmbufs, 1);
#endif
@@ -1033,6 +1120,21 @@ mac_destroy_vnode(struct vnode *vp)
mac_destroy_vnode_label(&vp->v_label);
}
+void
+mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
+{
+ struct label *src_label, *dest_label;
+
+ src_label = (struct label *)(src+1);
+ dest_label = (struct label *)(dest+1);
+
+ /*
+ * mac_init_mbuf_tag() is called on the target tag in
+ * m_tag_copy(), so we don't need to call it here.
+ */
+ MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
+}
+
static void
mac_copy_pipe_label(struct label *src, struct label *dest)
{
@@ -2318,13 +2420,12 @@ mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
struct label *label;
int error;
+ M_ASSERTPKTHDR(mbuf);
+
if (!mac_enforce_network)
return (0);
- M_ASSERTPKTHDR(mbuf);
label = mbuf_to_label(mbuf);
- if (!(label->l_flags & MAC_FLAG_INITIALIZED))
- if_printf(ifnet, "not initialized\n");
MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
label);
diff --git a/sys/security/mac/mac_system.c b/sys/security/mac/mac_system.c
index ff4ca4f..2650874 100644
--- a/sys/security/mac/mac_system.c
+++ b/sys/security/mac/mac_system.c
@@ -120,6 +120,21 @@ static int mac_late = 0;
*/
static int ea_warn_once = 0;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+/*
+ * Flag to indicate whether or not we should allocate label storage for
+ * new mbufs. Since most dynamic policies we currently work with don't
+ * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
+ * unless specifically notified of interest. One result of this is
+ * that if a dynamically loaded policy requests mbuf labels, it must
+ * be able to deal with a NULL label being returned on any mbufs that
+ * were already in flight when the policy was loaded. Since the policy
+ * already has to deal with uninitialized labels, this probably won't
+ * be a problem. Note: currently no locking. Will this be a problem?
+ */
+static int mac_labelmbufs = 0;
+#endif
+
static int mac_enforce_fs = 1;
SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
&mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
@@ -281,6 +296,12 @@ static int mac_policy_list_busy;
&mac_policy_list_lock); \
} while (0)
+#define MAC_POLICY_LIST_ASSERT_EXCLUSIVE() do { \
+ mtx_assert(&mac_policy_list_lock, MA_OWNED); \
+ KASSERT(mac_policy_list_busy == 0, \
+ ("MAC_POLICY_LIST_ASSERT_EXCLUSIVE()")); \
+} while (0)
+
#define MAC_POLICY_LIST_BUSY() do { \
MAC_POLICY_LIST_LOCK(); \
mac_policy_list_busy++; \
@@ -464,6 +485,35 @@ mac_late_init(void)
}
/*
+ * After the policy list has changed, walk the list to update any global
+ * flags.
+ */
+static void
+mac_policy_updateflags(void)
+{
+ struct mac_policy_conf *tmpc;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ int labelmbufs;
+#endif
+
+ MAC_POLICY_LIST_ASSERT_EXCLUSIVE();
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ labelmbufs = 0;
+#endif
+ LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
+ labelmbufs++;
+#endif
+ }
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ mac_labelmbufs = (labelmbufs != 0);
+#endif
+}
+
+/*
* Allow MAC policy modules to register during boot, etc.
*/
int
@@ -530,6 +580,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
/* Per-policy initialization. */
if (mpc->mpc_ops->mpo_init != NULL)
(*(mpc->mpc_ops->mpo_init))(mpc);
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
@@ -574,7 +625,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
LIST_REMOVE(mpc, mpc_list);
mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
-
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
@@ -623,9 +674,11 @@ error_select(int error1, int error2)
static struct label *
mbuf_to_label(struct mbuf *mbuf)
{
+ struct m_tag *tag;
struct label *label;
- label = &mbuf->m_pkthdr.label;
+ tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
+ label = (struct label *)(tag+1);
return (label);
}
@@ -727,20 +780,20 @@ mac_init_ipq(struct ipq *ipq, int flag)
}
int
-mac_init_mbuf(struct mbuf *m, int flag)
+mac_init_mbuf_tag(struct m_tag *tag, int flag)
{
- int error;
-
- M_ASSERTPKTHDR(m);
+ struct label *label;
+ int error, trflag;
- mac_init_label(&m->m_pkthdr.label);
+ label = (struct label *) (tag + 1);
+ mac_init_label(label);
- MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
+ trflag = (flag == M_DONTWAIT ? M_NOWAIT : M_WAITOK);
+ MAC_CHECK(init_mbuf_label, label, trflag);
if (error) {
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
}
-
#ifdef MAC_DEBUG
if (error == 0)
atomic_add_int(&nmacmbufs, 1);
@@ -748,6 +801,37 @@ mac_init_mbuf(struct mbuf *m, int flag)
return (error);
}
+int
+mac_init_mbuf(struct mbuf *m, int flag)
+{
+ struct m_tag *tag;
+ int error;
+
+ M_ASSERTPKTHDR(m);
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ /*
+ * Don't reserve space for labels on mbufs unless we have a policy
+ * that uses the labels.
+ */
+ if (mac_labelmbufs) {
+#endif
+ tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
+ flag);
+ if (tag == NULL)
+ return (ENOMEM);
+ error = mac_init_mbuf_tag(tag, flag);
+ if (error) {
+ m_tag_free(tag);
+ return (error);
+ }
+ m_tag_prepend(m, tag);
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ }
+#endif
+ return (0);
+}
+
void
mac_init_mount(struct mount *mp)
{
@@ -935,11 +1019,14 @@ mac_destroy_ipq(struct ipq *ipq)
}
void
-mac_destroy_mbuf(struct mbuf *m)
+mac_destroy_mbuf_tag(struct m_tag *tag)
{
+ struct label *label;
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ label = (struct label *)(tag+1);
+
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
#ifdef MAC_DEBUG
atomic_subtract_int(&nmacmbufs, 1);
#endif
@@ -1033,6 +1120,21 @@ mac_destroy_vnode(struct vnode *vp)
mac_destroy_vnode_label(&vp->v_label);
}
+void
+mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
+{
+ struct label *src_label, *dest_label;
+
+ src_label = (struct label *)(src+1);
+ dest_label = (struct label *)(dest+1);
+
+ /*
+ * mac_init_mbuf_tag() is called on the target tag in
+ * m_tag_copy(), so we don't need to call it here.
+ */
+ MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
+}
+
static void
mac_copy_pipe_label(struct label *src, struct label *dest)
{
@@ -2318,13 +2420,12 @@ mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
struct label *label;
int error;
+ M_ASSERTPKTHDR(mbuf);
+
if (!mac_enforce_network)
return (0);
- M_ASSERTPKTHDR(mbuf);
label = mbuf_to_label(mbuf);
- if (!(label->l_flags & MAC_FLAG_INITIALIZED))
- if_printf(ifnet, "not initialized\n");
MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
label);
diff --git a/sys/security/mac/mac_vfs.c b/sys/security/mac/mac_vfs.c
index ff4ca4f..2650874 100644
--- a/sys/security/mac/mac_vfs.c
+++ b/sys/security/mac/mac_vfs.c
@@ -120,6 +120,21 @@ static int mac_late = 0;
*/
static int ea_warn_once = 0;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+/*
+ * Flag to indicate whether or not we should allocate label storage for
+ * new mbufs. Since most dynamic policies we currently work with don't
+ * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
+ * unless specifically notified of interest. One result of this is
+ * that if a dynamically loaded policy requests mbuf labels, it must
+ * be able to deal with a NULL label being returned on any mbufs that
+ * were already in flight when the policy was loaded. Since the policy
+ * already has to deal with uninitialized labels, this probably won't
+ * be a problem. Note: currently no locking. Will this be a problem?
+ */
+static int mac_labelmbufs = 0;
+#endif
+
static int mac_enforce_fs = 1;
SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
&mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
@@ -281,6 +296,12 @@ static int mac_policy_list_busy;
&mac_policy_list_lock); \
} while (0)
+#define MAC_POLICY_LIST_ASSERT_EXCLUSIVE() do { \
+ mtx_assert(&mac_policy_list_lock, MA_OWNED); \
+ KASSERT(mac_policy_list_busy == 0, \
+ ("MAC_POLICY_LIST_ASSERT_EXCLUSIVE()")); \
+} while (0)
+
#define MAC_POLICY_LIST_BUSY() do { \
MAC_POLICY_LIST_LOCK(); \
mac_policy_list_busy++; \
@@ -464,6 +485,35 @@ mac_late_init(void)
}
/*
+ * After the policy list has changed, walk the list to update any global
+ * flags.
+ */
+static void
+mac_policy_updateflags(void)
+{
+ struct mac_policy_conf *tmpc;
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ int labelmbufs;
+#endif
+
+ MAC_POLICY_LIST_ASSERT_EXCLUSIVE();
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ labelmbufs = 0;
+#endif
+ LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
+ labelmbufs++;
+#endif
+ }
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ mac_labelmbufs = (labelmbufs != 0);
+#endif
+}
+
+/*
* Allow MAC policy modules to register during boot, etc.
*/
int
@@ -530,6 +580,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
/* Per-policy initialization. */
if (mpc->mpc_ops->mpo_init != NULL)
(*(mpc->mpc_ops->mpo_init))(mpc);
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
@@ -574,7 +625,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
LIST_REMOVE(mpc, mpc_list);
mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
-
+ mac_policy_updateflags();
MAC_POLICY_LIST_UNLOCK();
printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
@@ -623,9 +674,11 @@ error_select(int error1, int error2)
static struct label *
mbuf_to_label(struct mbuf *mbuf)
{
+ struct m_tag *tag;
struct label *label;
- label = &mbuf->m_pkthdr.label;
+ tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
+ label = (struct label *)(tag+1);
return (label);
}
@@ -727,20 +780,20 @@ mac_init_ipq(struct ipq *ipq, int flag)
}
int
-mac_init_mbuf(struct mbuf *m, int flag)
+mac_init_mbuf_tag(struct m_tag *tag, int flag)
{
- int error;
-
- M_ASSERTPKTHDR(m);
+ struct label *label;
+ int error, trflag;
- mac_init_label(&m->m_pkthdr.label);
+ label = (struct label *) (tag + 1);
+ mac_init_label(label);
- MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
+ trflag = (flag == M_DONTWAIT ? M_NOWAIT : M_WAITOK);
+ MAC_CHECK(init_mbuf_label, label, trflag);
if (error) {
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
}
-
#ifdef MAC_DEBUG
if (error == 0)
atomic_add_int(&nmacmbufs, 1);
@@ -748,6 +801,37 @@ mac_init_mbuf(struct mbuf *m, int flag)
return (error);
}
+int
+mac_init_mbuf(struct mbuf *m, int flag)
+{
+ struct m_tag *tag;
+ int error;
+
+ M_ASSERTPKTHDR(m);
+
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ /*
+ * Don't reserve space for labels on mbufs unless we have a policy
+ * that uses the labels.
+ */
+ if (mac_labelmbufs) {
+#endif
+ tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
+ flag);
+ if (tag == NULL)
+ return (ENOMEM);
+ error = mac_init_mbuf_tag(tag, flag);
+ if (error) {
+ m_tag_free(tag);
+ return (error);
+ }
+ m_tag_prepend(m, tag);
+#ifndef MAC_ALWAYS_LABEL_MBUF
+ }
+#endif
+ return (0);
+}
+
void
mac_init_mount(struct mount *mp)
{
@@ -935,11 +1019,14 @@ mac_destroy_ipq(struct ipq *ipq)
}
void
-mac_destroy_mbuf(struct mbuf *m)
+mac_destroy_mbuf_tag(struct m_tag *tag)
{
+ struct label *label;
- MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
- mac_destroy_label(&m->m_pkthdr.label);
+ label = (struct label *)(tag+1);
+
+ MAC_PERFORM(destroy_mbuf_label, label);
+ mac_destroy_label(label);
#ifdef MAC_DEBUG
atomic_subtract_int(&nmacmbufs, 1);
#endif
@@ -1033,6 +1120,21 @@ mac_destroy_vnode(struct vnode *vp)
mac_destroy_vnode_label(&vp->v_label);
}
+void
+mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
+{
+ struct label *src_label, *dest_label;
+
+ src_label = (struct label *)(src+1);
+ dest_label = (struct label *)(dest+1);
+
+ /*
+ * mac_init_mbuf_tag() is called on the target tag in
+ * m_tag_copy(), so we don't need to call it here.
+ */
+ MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
+}
+
static void
mac_copy_pipe_label(struct label *src, struct label *dest)
{
@@ -2318,13 +2420,12 @@ mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
struct label *label;
int error;
+ M_ASSERTPKTHDR(mbuf);
+
if (!mac_enforce_network)
return (0);
- M_ASSERTPKTHDR(mbuf);
label = mbuf_to_label(mbuf);
- if (!(label->l_flags & MAC_FLAG_INITIALIZED))
- if_printf(ifnet, "not initialized\n");
MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
label);
diff --git a/sys/sys/mac.h b/sys/sys/mac.h
index 3cc856d..77c33c4 100644
--- a/sys/sys/mac.h
+++ b/sys/sys/mac.h
@@ -109,6 +109,7 @@ struct ifnet;
struct ifreq;
struct image_params;
struct ipq;
+struct m_tag;
struct mbuf;
struct mount;
struct proc;
@@ -136,11 +137,13 @@ void mac_init_ifnet(struct ifnet *);
int mac_init_ipq(struct ipq *, int flag);
int mac_init_socket(struct socket *, int flag);
void mac_init_pipe(struct pipe *);
-int mac_init_mbuf(struct mbuf *m, int flag);
+int mac_init_mbuf(struct mbuf *mbuf, int flag);
+int mac_init_mbuf_tag(struct m_tag *, int flag);
void mac_init_mount(struct mount *);
void mac_init_proc(struct proc *);
void mac_init_vnode(struct vnode *);
void mac_init_vnode_label(struct label *);
+void mac_copy_mbuf_tag(struct m_tag *, struct m_tag *);
void mac_copy_vnode_label(struct label *, struct label *label);
void mac_destroy_bpfdesc(struct bpf_d *);
void mac_destroy_cred(struct ucred *);
@@ -150,7 +153,7 @@ void mac_destroy_ipq(struct ipq *);
void mac_destroy_socket(struct socket *);
void mac_destroy_pipe(struct pipe *);
void mac_destroy_proc(struct proc *);
-void mac_destroy_mbuf(struct mbuf *);
+void mac_destroy_mbuf_tag(struct m_tag *);
void mac_destroy_mount(struct mount *);
void mac_destroy_vnode(struct vnode *);
void mac_destroy_vnode_label(struct label *);
diff --git a/sys/sys/mac_policy.h b/sys/sys/mac_policy.h
index 4e00577..e3d649e 100644
--- a/sys/sys/mac_policy.h
+++ b/sys/sys/mac_policy.h
@@ -95,6 +95,8 @@ struct mac_policy_ops {
void (*mpo_destroy_pipe_label)(struct label *label);
void (*mpo_destroy_proc_label)(struct label *label);
void (*mpo_destroy_vnode_label)(struct label *label);
+ void (*mpo_copy_mbuf_label)(struct label *src,
+ struct label *dest);
void (*mpo_copy_pipe_label)(struct label *src,
struct label *dest);
void (*mpo_copy_vnode_label)(struct label *src,
@@ -431,6 +433,7 @@ struct mac_policy_conf {
/* Flags for the mpc_loadtime_flags field. */
#define MPC_LOADTIME_FLAG_NOTLATE 0x00000001
#define MPC_LOADTIME_FLAG_UNLOADOK 0x00000002
+#define MPC_LOADTIME_FLAG_LABELMBUFS 0x00000004
/* Flags for the mpc_runtime_flags field. */
#define MPC_RUNTIME_FLAG_REGISTERED 0x00000001
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index 2ebe84d..a00534a 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -37,7 +37,6 @@
#ifndef _SYS_MBUF_H_
#define _SYS_MBUF_H_
-#include <sys/_label.h>
#include <sys/queue.h>
/*
@@ -98,7 +97,6 @@ struct pkthdr {
int csum_flags; /* flags regarding checksum */
int csum_data; /* data field used by csum routines */
SLIST_HEAD(packet_tags, m_tag) tags; /* list of packet tags */
- struct label label; /* MAC label of data in packet */
};
/*
@@ -535,6 +533,7 @@ struct mbuf *m_split(struct mbuf *, int, int);
#define PACKET_TAG_IPFW 16 /* ipfw classification */
#define PACKET_TAG_DIVERT 17 /* divert info */
#define PACKET_TAG_IPFORWARD 18 /* ipforward info */
+#define PACKET_TAG_MACLABEL 19 /* MAC label */
/* Packet tag routines */
struct m_tag *m_tag_alloc(u_int32_t, int, int, int);
OpenPOWER on IntegriCloud