Move MAC label storage for mbufs into m_tags from the m_pkthdr structure,

returning some additional room in the first mbuf in a chain, and
avoiding feature-specific contents in the mbuf header.  To do this:

- Modify mbuf_to_label() to extract the tag, returning NULL if not
  found.

- Introduce mac_init_mbuf_tag() which does most of the work
  mac_init_mbuf() used to do, except on an m_tag rather than an
  mbuf.

- Scale back mac_init_mbuf() to perform m_tag allocation and invoke
  mac_init_mbuf_tag().

- Replace mac_destroy_mbuf() with mac_destroy_mbuf_tag(), since
  m_tag's are now GC'd deep in the m_tag/mbuf code rather than
  at a higher level when mbufs are directly free()'d.

- Add mac_copy_mbuf_tag() to support m_copy_pkthdr() and related
  notions.

- Generally change all references to mbuf labels so that they use
  mbuf_to_label() rather than &mbuf->m_pkthdr.label.  This
  required no changes in the MAC policies (yay!).

- Tweak mbuf release routines to not call mac_destroy_mbuf(),
  tag destruction takes care of it for us now.

- Remove MAC magic from m_copy_pkthdr() and m_move_pkthdr() --
  the existing m_tag support does all this for us.  Note that
  we can no longer just zero the m_tag list on the target mbuf,
  rather, we have to delete the chain because m_tag's will
  already be hung off freshly allocated mbuf's.

- Tweak m_tag copying routines so that if we're copying a MAC
  m_tag, we don't do a binary copy, rather, we initialize the
  new storage and do a deep copy of the label.

- Remove use of MAC_FLAG_INITIALIZED in a few bizarre places
  having to do with mbuf header copies previously.

- When an mbuf is copied in ip_input(), we no longer need to
  explicitly copy the label because it will get handled by the
  m_tag code now.

- No longer any weird handling of MAC labels in if_loop.c during
  header copies.

- Add MPC_LOADTIME_FLAG_LABELMBUFS flag to Biba, MLS, mac_test.
  In mac_test, handle the label==NULL case, since it can be
  dynamically loaded.

In order to improve performance with this change, introduce the notion
of "lazy MAC label allocation" -- only allocate m_tag storage for MAC
labels if we're running with a policy that uses MAC labels on mbufs.
Policies declare this intent by setting the MPC_LOADTIME_FLAG_LABELMBUFS
flag in their load-time flags field during declaration.  Note: this
opens up the possibility of post-boot policy modules getting back NULL
slot entries even though they have policy invariants of non-NULL slot
entries, as the policy might have been loaded after the mbuf was
allocated, leaving the mbuf without label storage.  Policies that cannot
handle this case must be declared as NOTLATE, or must be modified.

- mac_labelmbufs holds the current cumulative status as to whether
  any policies require mbuf labeling or not.  This is updated whenever
  the active policy set changes by the function mac_policy_updateflags().
  The function iterates the list and checks whether any have the
  flag set.  Write access to this variable is protected by the policy
  list; read access is currently not protected for performance reasons.
  This might change if it causes problems.

- Add MAC_POLICY_LIST_ASSERT_EXCLUSIVE() to permit the flags update
  function to assert appropriate locks.

- This makes allocation in mac_init_mbuf() conditional on the flag.

Reviewed by:	sam
Obtained from:	TrustedBSD Project
Sponsored by:	DARPA, Network Associates Laboratories
This commit is contained in:
Robert Watson 2003-04-14 20:39:06 +00:00
parent b85add5f31
commit 225bff6f8b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=113487
18 changed files with 1118 additions and 200 deletions

View File

@ -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++; \
@ -463,6 +484,35 @@ mac_late_init(void)
mac_late = 1;
}
/*
* 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.
*/
@ -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;
struct label *label;
int error, trflag;
M_ASSERTPKTHDR(m);
label = (struct label *) (tag + 1);
mac_init_label(label);
mac_init_label(&m->m_pkthdr.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);

View File

@ -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);

View File

@ -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)

View File

@ -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;
}

View File

@ -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);

View File

@ -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++; \
@ -463,6 +484,35 @@ mac_late_init(void)
mac_late = 1;
}
/*
* 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.
*/
@ -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;
struct label *label;
int error, trflag;
M_ASSERTPKTHDR(m);
label = (struct label *) (tag + 1);
mac_init_label(label);
mac_init_label(&m->m_pkthdr.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);

View File

@ -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 *);

View File

@ -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++; \
@ -463,6 +484,35 @@ mac_late_init(void)
mac_late = 1;
}
/*
* 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.
*/
@ -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;
struct label *label;
int error, trflag;
M_ASSERTPKTHDR(m);
label = (struct label *) (tag + 1);
mac_init_label(label);
mac_init_label(&m->m_pkthdr.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);

View File

@ -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++; \
@ -463,6 +484,35 @@ mac_late_init(void)
mac_late = 1;
}
/*
* 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.
*/
@ -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;
struct label *label;
int error, trflag;
M_ASSERTPKTHDR(m);
label = (struct label *) (tag + 1);
mac_init_label(label);
mac_init_label(&m->m_pkthdr.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);

View File

@ -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++; \
@ -463,6 +484,35 @@ mac_late_init(void)
mac_late = 1;
}
/*
* 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.
*/
@ -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;
struct label *label;
int error, trflag;
M_ASSERTPKTHDR(m);
label = (struct label *) (tag + 1);
mac_init_label(label);
mac_init_label(&m->m_pkthdr.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);

View File

@ -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

View File

@ -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++; \
@ -463,6 +484,35 @@ mac_late_init(void)
mac_late = 1;
}
/*
* 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.
*/
@ -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;
struct label *label;
int error, trflag;
M_ASSERTPKTHDR(m);
label = (struct label *) (tag + 1);
mac_init_label(label);
mac_init_label(&m->m_pkthdr.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);

View File

@ -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++; \
@ -463,6 +484,35 @@ mac_late_init(void)
mac_late = 1;
}
/*
* 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.
*/
@ -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;
struct label *label;
int error, trflag;
M_ASSERTPKTHDR(m);
label = (struct label *) (tag + 1);
mac_init_label(label);
mac_init_label(&m->m_pkthdr.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);

View File

@ -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++; \
@ -463,6 +484,35 @@ mac_late_init(void)
mac_late = 1;
}
/*
* 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.
*/
@ -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;
struct label *label;
int error, trflag;
M_ASSERTPKTHDR(m);
label = (struct label *) (tag + 1);
mac_init_label(label);
mac_init_label(&m->m_pkthdr.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);

View File

@ -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++; \
@ -463,6 +484,35 @@ mac_late_init(void)
mac_late = 1;
}
/*
* 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.
*/
@ -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;
struct label *label;
int error, trflag;
M_ASSERTPKTHDR(m);
label = (struct label *) (tag + 1);
mac_init_label(label);
mac_init_label(&m->m_pkthdr.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);

View File

@ -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 *);

View File

@ -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

View File

@ -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);