summaryrefslogtreecommitdiffstats
path: root/sys/security/mac
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-06-03 18:46:28 +0000
committerrwatson <rwatson@FreeBSD.org>2009-06-03 18:46:28 +0000
commit849a8ce20b26266bfcee925d683db20bee2a0ccd (patch)
treec959f41a3828e52e4d9970ee9fff5c64a88ca36e /sys/security/mac
parent673e1d1fc9eb778be5e4ca28de814387aca23ab8 (diff)
downloadFreeBSD-src-849a8ce20b26266bfcee925d683db20bee2a0ccd.zip
FreeBSD-src-849a8ce20b26266bfcee925d683db20bee2a0ccd.tar.gz
Continue work to optimize performance of "options MAC" when no MAC policy
modules are loaded by avoiding mbuf label lookups when policies aren't loaded, pushing further socket locking into MAC policy modules, and avoiding locking MAC ifnet locks when no policies are loaded: - Check mac_policies_count before looking for mbuf MAC label m_tags in MAC Framework entry points. We will still pay label lookup costs if MAC policies are present but don't require labels (typically a single mbuf header field read, but perhaps further indirection if IPSEC or other m_tag consumers are in use). - Further push socket locking for socket-related access control checks and events into MAC policies from the MAC Framework, so that sockets are only locked if a policy specifically requires a lock to protect a label. This resolves lock order issues during sonewconn() and also in local domain socket cross-connect where multiple socket locks could not be held at once for the purposes of propagatig MAC labels across multiple sockets. Eliminate mac_policy_count check in some entry points where it no longer avoids locking. - Add mac_policy_count checking in some entry points relating to network interfaces that otherwise lock a global MAC ifnet lock used to protect ifnet labels. Obtained from: TrustedBSD Project
Diffstat (limited to 'sys/security/mac')
-rw-r--r--sys/security/mac/mac_atalk.c3
-rw-r--r--sys/security/mac/mac_inet.c46
-rw-r--r--sys/security/mac/mac_inet6.c15
-rw-r--r--sys/security/mac/mac_net.c15
-rw-r--r--sys/security/mac/mac_socket.c76
5 files changed, 92 insertions, 63 deletions
diff --git a/sys/security/mac/mac_atalk.c b/sys/security/mac/mac_atalk.c
index 7ca338e..18bbb8d 100644
--- a/sys/security/mac/mac_atalk.c
+++ b/sys/security/mac/mac_atalk.c
@@ -61,6 +61,9 @@ mac_netatalk_aarp_send(struct ifnet *ifp, struct mbuf *m)
{
struct label *mlabel;
+ if (mac_policy_count == 0)
+ return;
+
mlabel = mac_mbuf_to_label(m);
MAC_IFNET_LOCK(ifp);
diff --git a/sys/security/mac/mac_inet.c b/sys/security/mac/mac_inet.c
index fd2c629..5753bb6 100644
--- a/sys/security/mac/mac_inet.c
+++ b/sys/security/mac/mac_inet.c
@@ -193,6 +193,9 @@ mac_ipq_reassemble(struct ipq *q, struct mbuf *m)
{
struct label *label;
+ if (mac_policy_count == 0)
+ return;
+
label = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(ipq_reassemble, q, q->ipq_label, m,
@@ -204,6 +207,9 @@ mac_netinet_fragment(struct mbuf *m, struct mbuf *frag)
{
struct label *mlabel, *fraglabel;
+ if (mac_policy_count == 0)
+ return;
+
mlabel = mac_mbuf_to_label(m);
fraglabel = mac_mbuf_to_label(frag);
@@ -216,6 +222,9 @@ mac_ipq_create(struct mbuf *m, struct ipq *q)
{
struct label *label;
+ if (mac_policy_count == 0)
+ return;
+
label = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(ipq_create, m, label, q, q->ipq_label);
@@ -227,6 +236,10 @@ mac_inpcb_create_mbuf(struct inpcb *inp, struct mbuf *m)
struct label *mlabel;
INP_LOCK_ASSERT(inp);
+
+ if (mac_policy_count == 0)
+ return;
+
mlabel = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(inpcb_create_mbuf, inp, inp->inp_label, m,
@@ -239,6 +252,9 @@ mac_ipq_match(struct mbuf *m, struct ipq *q)
struct label *label;
int result;
+ if (mac_policy_count == 0)
+ return (1);
+
label = mac_mbuf_to_label(m);
result = 1;
@@ -252,6 +268,9 @@ mac_netinet_arp_send(struct ifnet *ifp, struct mbuf *m)
{
struct label *mlabel;
+ if (mac_policy_count == 0)
+ return;
+
mlabel = mac_mbuf_to_label(m);
MAC_IFNET_LOCK(ifp);
@@ -265,6 +284,9 @@ mac_netinet_icmp_reply(struct mbuf *mrecv, struct mbuf *msend)
{
struct label *mrecvlabel, *msendlabel;
+ if (mac_policy_count == 0)
+ return;
+
mrecvlabel = mac_mbuf_to_label(mrecv);
msendlabel = mac_mbuf_to_label(msend);
@@ -277,6 +299,9 @@ mac_netinet_icmp_replyinplace(struct mbuf *m)
{
struct label *label;
+ if (mac_policy_count == 0)
+ return;
+
label = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(netinet_icmp_replyinplace, m, label);
@@ -287,6 +312,9 @@ mac_netinet_igmp_send(struct ifnet *ifp, struct mbuf *m)
{
struct label *mlabel;
+ if (mac_policy_count == 0)
+ return;
+
mlabel = mac_mbuf_to_label(m);
MAC_IFNET_LOCK(ifp);
@@ -300,6 +328,9 @@ mac_netinet_tcp_reply(struct mbuf *m)
{
struct label *label;
+ if (mac_policy_count == 0)
+ return;
+
label = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(netinet_tcp_reply, m, label);
@@ -310,6 +341,9 @@ mac_ipq_update(struct mbuf *m, struct ipq *q)
{
struct label *label;
+ if (mac_policy_count == 0)
+ return;
+
label = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(ipq_update, m, label, q, q->ipq_label);
@@ -326,6 +360,9 @@ mac_inpcb_check_deliver(struct inpcb *inp, struct mbuf *m)
M_ASSERTPKTHDR(m);
+ if (mac_policy_count == 0)
+ return (0);
+
label = mac_mbuf_to_label(m);
MAC_POLICY_CHECK_NOSLEEP(inpcb_check_deliver, inp, inp->inp_label, m,
@@ -371,6 +408,9 @@ mac_netinet_firewall_reply(struct mbuf *mrecv, struct mbuf *msend)
M_ASSERTPKTHDR(mrecv);
M_ASSERTPKTHDR(msend);
+ if (mac_policy_count == 0)
+ return;
+
mrecvlabel = mac_mbuf_to_label(mrecv);
msendlabel = mac_mbuf_to_label(msend);
@@ -385,6 +425,9 @@ mac_netinet_firewall_send(struct mbuf *m)
M_ASSERTPKTHDR(m);
+ if (mac_policy_count == 0)
+ return;
+
label = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(netinet_firewall_send, m, label);
@@ -455,6 +498,9 @@ mac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m)
M_ASSERTPKTHDR(m);
+ if (mac_policy_count == 0)
+ return;
+
mlabel = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(syncache_create_mbuf, sc_label, m,
diff --git a/sys/security/mac/mac_inet6.c b/sys/security/mac/mac_inet6.c
index be26a9d..a080a74 100644
--- a/sys/security/mac/mac_inet6.c
+++ b/sys/security/mac/mac_inet6.c
@@ -118,6 +118,9 @@ mac_ip6q_reassemble(struct ip6q *q6, struct mbuf *m)
{
struct label *label;
+ if (mac_policy_count == 0)
+ return;
+
label = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(ip6q_reassemble, q6, q6->ip6q_label, m,
@@ -129,6 +132,9 @@ mac_ip6q_create(struct mbuf *m, struct ip6q *q6)
{
struct label *label;
+ if (mac_policy_count == 0)
+ return;
+
label = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(ip6q_create, m, label, q6,
@@ -141,6 +147,9 @@ mac_ip6q_match(struct mbuf *m, struct ip6q *q6)
struct label *label;
int result;
+ if (mac_policy_count == 0)
+ return (1);
+
label = mac_mbuf_to_label(m);
result = 1;
@@ -155,6 +164,9 @@ mac_ip6q_update(struct mbuf *m, struct ip6q *q6)
{
struct label *label;
+ if (mac_policy_count == 0)
+ return;
+
label = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(ip6q_update, m, label, q6,
@@ -166,6 +178,9 @@ mac_netinet6_nd6_send(struct ifnet *ifp, struct mbuf *m)
{
struct label *mlabel;
+ if (mac_policy_count == 0)
+ return;
+
mlabel = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(netinet6_nd6_send, ifp, ifp->if_label, m,
diff --git a/sys/security/mac/mac_net.c b/sys/security/mac/mac_net.c
index ecd4195..73154148 100644
--- a/sys/security/mac/mac_net.c
+++ b/sys/security/mac/mac_net.c
@@ -296,6 +296,9 @@ void
mac_ifnet_create(struct ifnet *ifp)
{
+ if (mac_policy_count == 0)
+ return;
+
MAC_IFNET_LOCK(ifp);
MAC_POLICY_PERFORM_NOSLEEP(ifnet_create, ifp, ifp->if_label);
MAC_IFNET_UNLOCK(ifp);
@@ -315,6 +318,9 @@ mac_bpfdesc_create_mbuf(struct bpf_d *d, struct mbuf *m)
BPFD_LOCK_ASSERT(d);
+ if (mac_policy_count == 0)
+ return;
+
label = mac_mbuf_to_label(m);
MAC_POLICY_PERFORM_NOSLEEP(bpfdesc_create_mbuf, d, d->bd_label, m,
@@ -326,6 +332,9 @@ mac_ifnet_create_mbuf(struct ifnet *ifp, struct mbuf *m)
{
struct label *label;
+ if (mac_policy_count == 0)
+ return;
+
label = mac_mbuf_to_label(m);
MAC_IFNET_LOCK(ifp);
@@ -344,6 +353,9 @@ mac_bpfdesc_check_receive(struct bpf_d *d, struct ifnet *ifp)
BPFD_LOCK_ASSERT(d);
+ if (mac_policy_count == 0)
+ return (0);
+
MAC_IFNET_LOCK(ifp);
MAC_POLICY_CHECK_NOSLEEP(bpfdesc_check_receive, d, d->bd_label, ifp,
ifp->if_label);
@@ -364,6 +376,9 @@ mac_ifnet_check_transmit(struct ifnet *ifp, struct mbuf *m)
M_ASSERTPKTHDR(m);
+ if (mac_policy_count == 0)
+ return (0);
+
label = mac_mbuf_to_label(m);
MAC_IFNET_LOCK(ifp);
diff --git a/sys/security/mac/mac_socket.c b/sys/security/mac/mac_socket.c
index 704c60b..11d5e05 100644
--- a/sys/security/mac/mac_socket.c
+++ b/sys/security/mac/mac_socket.c
@@ -88,6 +88,16 @@ __FBSDID("$FreeBSD$");
* remote socket for UNIX domain sockets rather than keeping a local copy on
* this endpoint, but be cached and updated based on packets received for
* TCP/IP.
+ *
+ * Unlike with many other object types, the lock protecting MAC labels on
+ * sockets (the socket lock) is not frequently held at the points in code
+ * where socket-related checks are called. The MAC Framework acquires the
+ * lock over some entry points in order to enforce atomicity (such as label
+ * copies) but in other cases the policy modules will have to acquire the
+ * lock themselves if they use labels. This approach (a) avoids lock
+ * acquisitions when policies don't require labels and (b) solves a number of
+ * potential lock order issues when multiple sockets are used in the same
+ * entry point.
*/
struct label *
@@ -234,13 +244,8 @@ void
mac_socket_newconn(struct socket *oldso, struct socket *newso)
{
- if (mac_policy_count == 0)
- return;
-
- SOCK_LOCK(oldso);
MAC_POLICY_PERFORM_NOSLEEP(socket_newconn, oldso, oldso->so_label,
newso, newso->so_label);
- SOCK_UNLOCK(oldso);
}
static void
@@ -259,12 +264,13 @@ mac_socketpeer_set_from_mbuf(struct mbuf *m, struct socket *so)
{
struct label *label;
+ if (mac_policy_count == 0)
+ return;
+
label = mac_mbuf_to_label(m);
- SOCK_LOCK(so);
MAC_POLICY_PERFORM_NOSLEEP(socketpeer_set_from_mbuf, m, label, so,
so->so_peerlabel);
- SOCK_UNLOCK(so);
}
void
@@ -274,15 +280,8 @@ mac_socketpeer_set_from_socket(struct socket *oldso, struct socket *newso)
if (mac_policy_count == 0)
return;
- /*
- * XXXRW: We want to hold locks on both sockets, but can't currently
- * due to lock order -- opt to lock the socket where we're accessing
- * so_label as it's more likely to change.
- */
- SOCK_LOCK(oldso);
MAC_POLICY_PERFORM_NOSLEEP(socketpeer_set_from_socket, oldso,
oldso->so_label, newso, newso->so_peerlabel);
- SOCK_UNLOCK(oldso);
}
void
@@ -295,10 +294,8 @@ mac_socket_create_mbuf(struct socket *so, struct mbuf *m)
label = mac_mbuf_to_label(m);
- SOCK_LOCK(so);
MAC_POLICY_PERFORM_NOSLEEP(socket_create_mbuf, so, so->so_label, m,
label);
- SOCK_UNLOCK(so);
}
MAC_CHECK_PROBE_DEFINE2(socket_check_accept, "struct ucred *",
@@ -309,14 +306,9 @@ mac_socket_check_accept(struct ucred *cred, struct socket *so)
{
int error;
- if (mac_policy_count == 0)
- return (0);
-
- SOCK_LOCK(so);
MAC_POLICY_CHECK_NOSLEEP(socket_check_accept, cred, so,
so->so_label);
MAC_CHECK_PROBE2(socket_check_accept, error, cred, so);
- SOCK_UNLOCK(so);
return (error);
}
@@ -330,14 +322,9 @@ mac_socket_check_bind(struct ucred *cred, struct socket *so,
{
int error;
- if (mac_policy_count == 0)
- return (0);
-
- SOCK_LOCK(so);
MAC_POLICY_CHECK_NOSLEEP(socket_check_bind, cred, so, so->so_label,
sa);
MAC_CHECK_PROBE3(socket_check_bind, error, cred, so, sa);
- SOCK_UNLOCK(so);
return (error);
}
@@ -351,14 +338,9 @@ mac_socket_check_connect(struct ucred *cred, struct socket *so,
{
int error;
- if (mac_policy_count == 0)
- return (0);
-
- SOCK_LOCK(so);
MAC_POLICY_CHECK_NOSLEEP(socket_check_connect, cred, so,
so->so_label, sa);
MAC_CHECK_PROBE3(socket_check_connect, error, cred, so, sa);
- SOCK_UNLOCK(so);
return (error);
}
@@ -393,11 +375,9 @@ mac_socket_check_deliver(struct socket *so, struct mbuf *m)
label = mac_mbuf_to_label(m);
- SOCK_LOCK(so);
MAC_POLICY_CHECK_NOSLEEP(socket_check_deliver, so, so->so_label, m,
label);
MAC_CHECK_PROBE2(socket_check_deliver, error, so, m);
- SOCK_UNLOCK(so);
return (error);
}
@@ -410,14 +390,9 @@ mac_socket_check_listen(struct ucred *cred, struct socket *so)
{
int error;
- if (mac_policy_count == 0)
- return (0);
-
- SOCK_LOCK(so);
MAC_POLICY_CHECK_NOSLEEP(socket_check_listen, cred, so,
so->so_label);
MAC_CHECK_PROBE2(socket_check_listen, error, cred, so);
- SOCK_UNLOCK(so);
return (error);
}
@@ -430,13 +405,8 @@ mac_socket_check_poll(struct ucred *cred, struct socket *so)
{
int error;
- if (mac_policy_count == 0)
- return (0);
-
- SOCK_LOCK(so);
MAC_POLICY_CHECK_NOSLEEP(socket_check_poll, cred, so, so->so_label);
MAC_CHECK_PROBE2(socket_check_poll, error, cred, so);
- SOCK_UNLOCK(so);
return (error);
}
@@ -449,14 +419,9 @@ mac_socket_check_receive(struct ucred *cred, struct socket *so)
{
int error;
- if (mac_policy_count == 0)
- return (0);
-
- SOCK_LOCK(so);
MAC_POLICY_CHECK_NOSLEEP(socket_check_receive, cred, so,
so->so_label);
MAC_CHECK_PROBE2(socket_check_receive, error, cred, so);
- SOCK_UNLOCK(so);
return (error);
}
@@ -487,13 +452,8 @@ mac_socket_check_send(struct ucred *cred, struct socket *so)
{
int error;
- if (mac_policy_count == 0)
- return (0);
-
- SOCK_LOCK(so);
MAC_POLICY_CHECK_NOSLEEP(socket_check_send, cred, so, so->so_label);
MAC_CHECK_PROBE2(socket_check_send, error, cred, so);
- SOCK_UNLOCK(so);
return (error);
}
@@ -506,13 +466,8 @@ mac_socket_check_stat(struct ucred *cred, struct socket *so)
{
int error;
- if (mac_policy_count == 0)
- return (0);
-
- SOCK_LOCK(so);
MAC_POLICY_CHECK_NOSLEEP(socket_check_stat, cred, so, so->so_label);
MAC_CHECK_PROBE2(socket_check_stat, error, cred, so);
- SOCK_UNLOCK(so);
return (error);
}
@@ -525,14 +480,9 @@ mac_socket_check_visible(struct ucred *cred, struct socket *so)
{
int error;
- if (mac_policy_count == 0)
- return (0);
-
- SOCK_LOCK(so);
MAC_POLICY_CHECK_NOSLEEP(socket_check_visible, cred, so,
so->so_label);
MAC_CHECK_PROBE2(socket_check_visible, error, cred, so);
- SOCK_UNLOCK(so);
return (error);
}
OpenPOWER on IntegriCloud