summaryrefslogtreecommitdiffstats
path: root/sys/security/mac/mac_pipe.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2003-04-14 20:39:06 +0000
committerrwatson <rwatson@FreeBSD.org>2003-04-14 20:39:06 +0000
commit53a050aac3fa734d90417e05216e4a2bdaa259e4 (patch)
tree4a1b631e9b980e33ec2ea5040a1b9787eeda9f33 /sys/security/mac/mac_pipe.c
parent26efa7aed0e678061759d33ffd8b770063a81f5a (diff)
downloadFreeBSD-src-53a050aac3fa734d90417e05216e4a2bdaa259e4.zip
FreeBSD-src-53a050aac3fa734d90417e05216e4a2bdaa259e4.tar.gz
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
Diffstat (limited to 'sys/security/mac/mac_pipe.c')
-rw-r--r--sys/security/mac/mac_pipe.c135
1 files changed, 118 insertions, 17 deletions
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);
OpenPOWER on IntegriCloud