summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-06-02 18:26:17 +0000
committerrwatson <rwatson@FreeBSD.org>2009-06-02 18:26:17 +0000
commit0f9e85844038f1065732f6e28261101bb0c61492 (patch)
tree9f93a531fd61b5932ab6fcc38f6915b3f1a0ab60
parent12453fdf4f537f30c14a82fa93b74dd48d24775b (diff)
downloadFreeBSD-src-0f9e85844038f1065732f6e28261101bb0c61492.zip
FreeBSD-src-0f9e85844038f1065732f6e28261101bb0c61492.tar.gz
Add internal 'mac_policy_count' counter to the MAC Framework, which is a
count of the number of registered policies. Rather than unconditionally locking sockets before passing them into MAC, lock them in the MAC entry points only if mac_policy_count is non-zero. This avoids locking overhead for a number of socket system calls when no policies are registered, eliminating measurable overhead for the MAC Framework for the socket subsystem when there are no active policies. Possibly socket locks should be acquired by policies if they are required for socket labels, which would further avoid locking overhead when there are policies but they don't require labeling of sockets, or possibly don't even implement socket controls. Obtained from: TrustedBSD Project
-rw-r--r--sys/kern/kern_prot.c2
-rw-r--r--sys/kern/sys_socket.c8
-rw-r--r--sys/kern/uipc_socket.c2
-rw-r--r--sys/kern/uipc_syscalls.c48
-rw-r--r--sys/kern/uipc_usrreq.c2
-rw-r--r--sys/netatalk/ddp_input.c6
-rw-r--r--sys/netinet/ip_divert.c2
-rw-r--r--sys/netinet/tcp_input.c2
-rw-r--r--sys/netinet/tcp_syncache.c2
-rw-r--r--sys/rpc/svc_vc.c2
-rw-r--r--sys/security/mac/mac_framework.c16
-rw-r--r--sys/security/mac/mac_internal.h1
-rw-r--r--sys/security/mac/mac_socket.c75
13 files changed, 83 insertions, 85 deletions
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index a1a55f2..4e0bdf0 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -1690,9 +1690,7 @@ cr_canseesocket(struct ucred *cred, struct socket *so)
if (error)
return (ENOENT);
#ifdef MAC
- SOCK_LOCK(so);
error = mac_socket_check_visible(cred, so);
- SOCK_UNLOCK(so);
if (error)
return (error);
#endif
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
index 61b0361..5e5695c 100644
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -78,9 +78,7 @@ soo_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
int error;
#ifdef MAC
- SOCK_LOCK(so);
error = mac_socket_check_receive(active_cred, so);
- SOCK_UNLOCK(so);
if (error)
return (error);
#endif
@@ -99,9 +97,7 @@ soo_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
int error;
#ifdef MAC
- SOCK_LOCK(so);
error = mac_socket_check_send(active_cred, so);
- SOCK_UNLOCK(so);
if (error)
return (error);
#endif
@@ -222,9 +218,7 @@ soo_poll(struct file *fp, int events, struct ucred *active_cred,
#ifdef MAC
int error;
- SOCK_LOCK(so);
error = mac_socket_check_poll(active_cred, so);
- SOCK_UNLOCK(so);
if (error)
return (error);
#endif
@@ -243,9 +237,7 @@ soo_stat(struct file *fp, struct stat *ub, struct ucred *active_cred,
bzero((caddr_t)ub, sizeof (*ub));
ub->st_mode = S_IFSOCK;
#ifdef MAC
- SOCK_LOCK(so);
error = mac_socket_check_stat(active_cred, so);
- SOCK_UNLOCK(so);
if (error)
return (error);
#endif
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 80f9a55..7341d3f 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -444,9 +444,7 @@ sonewconn(struct socket *head, int connstatus)
so->so_proto = head->so_proto;
so->so_cred = crhold(head->so_cred);
#ifdef MAC
- SOCK_LOCK(head);
mac_socket_newconn(head, so);
- SOCK_UNLOCK(head);
#endif
knlist_init(&so->so_rcv.sb_sel.si_note, SOCKBUF_MTX(&so->so_rcv),
NULL, NULL, NULL);
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 66eb7e1..964547c 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -221,16 +221,10 @@ kern_bind(td, fd, sa)
ktrsockaddr(sa);
#endif
#ifdef MAC
- SOCK_LOCK(so);
error = mac_socket_check_bind(td->td_ucred, so, sa);
- SOCK_UNLOCK(so);
- if (error)
- goto done;
-#endif
- error = sobind(so, sa, td);
-#ifdef MAC
-done:
+ if (error == 0)
#endif
+ error = sobind(so, sa, td);
fdrop(fp, td);
return (error);
}
@@ -252,17 +246,14 @@ listen(td, uap)
if (error == 0) {
so = fp->f_data;
#ifdef MAC
- SOCK_LOCK(so);
error = mac_socket_check_listen(td->td_ucred, so);
- SOCK_UNLOCK(so);
- if (error)
- goto done;
+ if (error == 0) {
#endif
- CURVNET_SET(so->so_vnet);
- error = solisten(so, uap->backlog, td);
- CURVNET_RESTORE();
+ CURVNET_SET(so->so_vnet);
+ error = solisten(so, uap->backlog, td);
+ CURVNET_RESTORE();
#ifdef MAC
-done:
+ }
#endif
fdrop(fp, td);
}
@@ -354,9 +345,7 @@ kern_accept(struct thread *td, int s, struct sockaddr **name,
goto done;
}
#ifdef MAC
- SOCK_LOCK(head);
error = mac_socket_check_accept(td->td_ucred, head);
- SOCK_UNLOCK(head);
if (error != 0)
goto done;
#endif
@@ -549,9 +538,7 @@ kern_connect(td, fd, sa)
ktrsockaddr(sa);
#endif
#ifdef MAC
- SOCK_LOCK(so);
error = mac_socket_check_connect(td->td_ucred, so, sa);
- SOCK_UNLOCK(so);
if (error)
goto bad;
#endif
@@ -603,7 +590,6 @@ kern_socketpair(struct thread *td, int domain, int type, int protocol,
if (error)
return (error);
#endif
-
error = socreate(domain, &so1, type, protocol, td->td_ucred, td);
if (error)
return (error);
@@ -752,13 +738,13 @@ kern_sendit(td, s, mp, flags, control, segflg)
so = (struct socket *)fp->f_data;
#ifdef MAC
- SOCK_LOCK(so);
- if (mp->msg_name != NULL)
+ if (mp->msg_name != NULL) {
error = mac_socket_check_connect(td->td_ucred, so,
mp->msg_name);
- if (error == 0)
- error = mac_socket_check_send(td->td_ucred, so);
- SOCK_UNLOCK(so);
+ if (error)
+ goto bad;
+ }
+ error = mac_socket_check_send(td->td_ucred, so);
if (error)
goto bad;
#endif
@@ -951,9 +937,7 @@ kern_recvit(td, s, mp, fromseg, controlp)
so = fp->f_data;
#ifdef MAC
- SOCK_LOCK(so);
error = mac_socket_check_receive(td->td_ucred, so);
- SOCK_UNLOCK(so);
if (error) {
fdrop(fp, td);
return (error);
@@ -1887,9 +1871,7 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap,
}
#ifdef MAC
- SOCK_LOCK(so);
error = mac_socket_check_send(td->td_ucred, so);
- SOCK_UNLOCK(so);
if (error)
goto out;
#endif
@@ -2417,9 +2399,7 @@ sctp_generic_sendmsg (td, uap)
so = (struct socket *)fp->f_data;
#ifdef MAC
- SOCK_LOCK(so);
error = mac_socket_check_send(td->td_ucred, so);
- SOCK_UNLOCK(so);
if (error)
goto sctp_bad;
#endif /* MAC */
@@ -2521,9 +2501,7 @@ sctp_generic_sendmsg_iov(td, uap)
so = (struct socket *)fp->f_data;
#ifdef MAC
- SOCK_LOCK(so);
error = mac_socket_check_send(td->td_ucred, so);
- SOCK_UNLOCK(so);
if (error)
goto sctp_bad;
#endif /* MAC */
@@ -2618,9 +2596,7 @@ sctp_generic_recvmsg(td, uap)
so = fp->f_data;
#ifdef MAC
- SOCK_LOCK(so);
error = mac_socket_check_receive(td->td_ucred, so);
- SOCK_UNLOCK(so);
if (error) {
goto out;
return (error);
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 2f33008..c9e7d39 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -1246,10 +1246,8 @@ unp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
UNP_PCB_UNLOCK(unp2);
UNP_PCB_UNLOCK(unp);
#ifdef MAC
- SOCK_LOCK(so);
mac_socketpeer_set_from_socket(so, so3);
mac_socketpeer_set_from_socket(so3, so);
- SOCK_UNLOCK(so);
#endif
so2 = so3;
diff --git a/sys/netatalk/ddp_input.c b/sys/netatalk/ddp_input.c
index 2e7dac8..d90b2e8 100644
--- a/sys/netatalk/ddp_input.c
+++ b/sys/netatalk/ddp_input.c
@@ -410,12 +410,8 @@ ddp_input(struct mbuf *m, struct ifnet *ifp, struct elaphdr *elh, int phase)
goto out;
#ifdef MAC
- SOCK_LOCK(ddp->ddp_socket);
- if (mac_socket_check_deliver(ddp->ddp_socket, m) != 0) {
- SOCK_UNLOCK(ddp->ddp_socket);
+ if (mac_socket_check_deliver(ddp->ddp_socket, m) != 0)
goto out;
- }
- SOCK_UNLOCK(ddp->ddp_socket);
#endif
/*
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c
index 5e71d4d..0894bfa4 100644
--- a/sys/netinet/ip_divert.c
+++ b/sys/netinet/ip_divert.c
@@ -467,9 +467,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin,
m->m_pkthdr.rcvif = ifa->ifa_ifp;
}
#ifdef MAC
- SOCK_LOCK(so);
mac_socket_create_mbuf(so, m);
- SOCK_UNLOCK(so);
#endif
/* Send packet to input processing via netisr */
netisr_queue_src(NETISR_IP, (uintptr_t)so, m);
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index bbf5d8f..674c77e 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1562,9 +1562,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
TCPSTAT_INC(tcps_connects);
soisconnected(so);
#ifdef MAC
- SOCK_LOCK(so);
mac_socketpeer_set_from_mbuf(m, so);
- SOCK_UNLOCK(so);
#endif
/* Do window scaling on this connection? */
if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 8e80842..2763183 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -635,9 +635,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
goto abort2;
}
#ifdef MAC
- SOCK_LOCK(so);
mac_socketpeer_set_from_mbuf(m, so);
- SOCK_UNLOCK(so);
#endif
inp = sotoinpcb(so);
diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c
index 9f6a4a4..be366de 100644
--- a/sys/rpc/svc_vc.c
+++ b/sys/rpc/svc_vc.c
@@ -271,9 +271,7 @@ svc_vc_accept(struct socket *head, struct socket **sop)
goto done;
}
#ifdef MAC
- SOCK_LOCK(head);
error = mac_socket_check_accept(td->td_ucred, head);
- SOCK_UNLOCK(head);
if (error != 0)
goto done;
#endif
diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c
index 6f675cb..3d2a139 100644
--- a/sys/security/mac/mac_framework.c
+++ b/sys/security/mac/mac_framework.c
@@ -179,6 +179,7 @@ static struct sx mac_policy_sx; /* Sleeping entry points. */
struct mac_policy_list_head mac_policy_list;
struct mac_policy_list_head mac_static_policy_list;
+u_int mac_policy_count; /* Registered policy count. */
static void mac_policy_xlock(void);
static void mac_policy_xlock_assert(void);
@@ -351,17 +352,22 @@ mac_policy_getlabeled(struct mac_policy_conf *mpc)
* requiring labels across all policies.
*/
static void
-mac_policy_updateflags(void)
+mac_policy_update(void)
{
struct mac_policy_conf *mpc;
mac_policy_xlock_assert();
mac_labeled = 0;
- LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list)
+ mac_policy_count = 0;
+ LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
mac_labeled |= mac_policy_getlabeled(mpc);
- LIST_FOREACH(mpc, &mac_policy_list, mpc_list)
+ mac_policy_count++;
+ }
+ LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
mac_labeled |= mac_policy_getlabeled(mpc);
+ mac_policy_count++;
+ }
}
static int
@@ -434,7 +440,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
*/
if (mpc->mpc_ops->mpo_init != NULL)
(*(mpc->mpc_ops->mpo_init))(mpc);
- mac_policy_updateflags();
+ mac_policy_update();
SDT_PROBE(mac, kernel, policy, register, mpc, 0, 0, 0, 0);
printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
@@ -480,7 +486,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_update();
mac_policy_xunlock();
SDT_PROBE(mac, kernel, policy, unregister, mpc, 0, 0, 0, 0);
diff --git a/sys/security/mac/mac_internal.h b/sys/security/mac/mac_internal.h
index 45bd524..39fc404 100644
--- a/sys/security/mac/mac_internal.h
+++ b/sys/security/mac/mac_internal.h
@@ -189,6 +189,7 @@ struct label {
*/
extern struct mac_policy_list_head mac_policy_list;
extern struct mac_policy_list_head mac_static_policy_list;
+extern u_int mac_policy_count;
extern uint64_t mac_labeled;
extern struct mtx mac_ifnet_mtx;
diff --git a/sys/security/mac/mac_socket.c b/sys/security/mac/mac_socket.c
index 25f8dae..704c60b 100644
--- a/sys/security/mac/mac_socket.c
+++ b/sys/security/mac/mac_socket.c
@@ -234,10 +234,13 @@ void
mac_socket_newconn(struct socket *oldso, struct socket *newso)
{
- SOCK_LOCK_ASSERT(oldso);
+ 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
@@ -256,25 +259,30 @@ mac_socketpeer_set_from_mbuf(struct mbuf *m, struct socket *so)
{
struct label *label;
- SOCK_LOCK_ASSERT(so);
-
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
mac_socketpeer_set_from_socket(struct socket *oldso, struct socket *newso)
{
+
+ if (mac_policy_count == 0)
+ return;
/*
- * XXXRW: only hold the socket lock on one at a time, as one socket
- * is the original, and one is the new. However, it's called in both
- * directions, so we can't assert the lock here currently.
+ * 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
@@ -282,12 +290,15 @@ mac_socket_create_mbuf(struct socket *so, struct mbuf *m)
{
struct label *label;
- SOCK_LOCK_ASSERT(so);
+ if (mac_policy_count == 0)
+ return;
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 *",
@@ -298,11 +309,14 @@ mac_socket_check_accept(struct ucred *cred, struct socket *so)
{
int error;
- SOCK_LOCK_ASSERT(so);
+ 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);
}
@@ -316,11 +330,14 @@ mac_socket_check_bind(struct ucred *cred, struct socket *so,
{
int error;
- SOCK_LOCK_ASSERT(so);
+ 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);
}
@@ -334,11 +351,14 @@ mac_socket_check_connect(struct ucred *cred, struct socket *so,
{
int error;
- SOCK_LOCK_ASSERT(so);
+ 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);
}
@@ -368,13 +388,16 @@ mac_socket_check_deliver(struct socket *so, struct mbuf *m)
struct label *label;
int error;
- SOCK_LOCK_ASSERT(so);
+ if (mac_policy_count == 0)
+ return (0);
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);
}
@@ -387,11 +410,14 @@ mac_socket_check_listen(struct ucred *cred, struct socket *so)
{
int error;
- SOCK_LOCK_ASSERT(so);
+ 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);
}
@@ -404,10 +430,13 @@ mac_socket_check_poll(struct ucred *cred, struct socket *so)
{
int error;
- SOCK_LOCK_ASSERT(so);
+ 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);
}
@@ -420,11 +449,14 @@ mac_socket_check_receive(struct ucred *cred, struct socket *so)
{
int error;
- SOCK_LOCK_ASSERT(so);
+ 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);
}
@@ -455,10 +487,13 @@ mac_socket_check_send(struct ucred *cred, struct socket *so)
{
int error;
- SOCK_LOCK_ASSERT(so);
+ 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);
}
@@ -471,10 +506,13 @@ mac_socket_check_stat(struct ucred *cred, struct socket *so)
{
int error;
- SOCK_LOCK_ASSERT(so);
+ 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);
}
@@ -487,11 +525,14 @@ mac_socket_check_visible(struct ucred *cred, struct socket *so)
{
int error;
- SOCK_LOCK_ASSERT(so);
+ 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