summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2017-11-13 17:00:15 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2017-11-13 17:00:15 +0000
commit1d4caf6d1b91d1ea98aef189ed3d31f2179882c3 (patch)
tree50b7ca2baddfdee5be293e4d8023bf63ce47de94
parent0542bf745efc81d71934e43e5316fee595807eff (diff)
Grab the KERNEL_LOCK() to iterate on the global list of PF_KEY sockets.
It isn't safe to manipulate PF_KEY sockets without KERNEL_LOCK() because they aren't protected by the NET_LOCK(). I missed this in my previous audit and neither my tests, the regression tests nor the IPsec performance tests exposed the problem. Hopefully I added the right check to soassertlocked() a while back. Found the hardway by and ok sthen@
-rw-r--r--sys/net/pfkeyv2.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c
index f80f98a7eb6..886770b4d1f 100644
--- a/sys/net/pfkeyv2.c
+++ b/sys/net/pfkeyv2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfkeyv2.c,v 1.173 2017/11/12 14:11:15 mpi Exp $ */
+/* $OpenBSD: pfkeyv2.c,v 1.174 2017/11/13 17:00:14 mpi Exp $ */
/*
* @(#)COPYRIGHT 1.1 (NRL) 17 January 1995
@@ -428,12 +428,14 @@ pfkeyv2_sendmessage(void **headers, int mode, struct socket *so,
* Search for promiscuous listeners, skipping the
* original destination.
*/
+ KERNEL_LOCK();
LIST_FOREACH(s, &pfkeyv2_sockets, kcb_list) {
if ((s->flags & PFKEYV2_SOCKETFLAGS_PROMISC) &&
(s->rcb.rcb_socket != so) &&
(s->rdomain == rdomain))
pfkey_sendup(s, packet, 1);
}
+ KERNEL_UNLOCK();
m_freem(packet);
break;
@@ -442,6 +444,7 @@ pfkeyv2_sendmessage(void **headers, int mode, struct socket *so,
* Send the message to all registered sockets that match
* the specified satype (e.g., all IPSEC-ESP negotiators)
*/
+ KERNEL_LOCK();
LIST_FOREACH(s, &pfkeyv2_sockets, kcb_list) {
if ((s->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) &&
(s->rdomain == rdomain)) {
@@ -454,6 +457,7 @@ pfkeyv2_sendmessage(void **headers, int mode, struct socket *so,
}
}
}
+ KERNEL_UNLOCK();
/* Free last/original copy of the packet */
m_freem(packet);
@@ -472,21 +476,25 @@ pfkeyv2_sendmessage(void **headers, int mode, struct socket *so,
goto ret;
/* Send to all registered promiscuous listeners */
+ KERNEL_LOCK();
LIST_FOREACH(s, &pfkeyv2_sockets, kcb_list) {
if ((s->flags & PFKEYV2_SOCKETFLAGS_PROMISC) &&
!(s->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) &&
(s->rdomain == rdomain))
pfkey_sendup(s, packet, 1);
}
+ KERNEL_UNLOCK();
m_freem(packet);
break;
case PFKEYV2_SENDMESSAGE_BROADCAST:
/* Send message to all sockets */
+ KERNEL_LOCK();
LIST_FOREACH(s, &pfkeyv2_sockets, kcb_list) {
if (s->rdomain == rdomain)
pfkey_sendup(s, packet, 1);
}
+ KERNEL_UNLOCK();
m_freem(packet);
break;
}
@@ -1010,11 +1018,13 @@ pfkeyv2_send(struct socket *so, void *message, int len)
goto ret;
/* Send to all promiscuous listeners */
+ KERNEL_LOCK();
LIST_FOREACH(bkp, &pfkeyv2_sockets, kcb_list) {
if ((bkp->flags & PFKEYV2_SOCKETFLAGS_PROMISC) &&
(bkp->rdomain == rdomain))
pfkey_sendup(bkp, packet, 1);
}
+ KERNEL_UNLOCK();
m_freem(packet);
@@ -1788,12 +1798,15 @@ pfkeyv2_send(struct socket *so, void *message, int len)
if ((rval = pfdatatopacket(message, len, &packet)) != 0)
goto ret;
- LIST_FOREACH(bkp, &pfkeyv2_sockets, kcb_list)
+ KERNEL_LOCK();
+ LIST_FOREACH(bkp, &pfkeyv2_sockets, kcb_list) {
if ((bkp != kp) &&
(bkp->rdomain == rdomain) &&
(!smsg->sadb_msg_seq ||
(smsg->sadb_msg_seq == kp->pid)))
pfkey_sendup(bkp, packet, 1);
+ }
+ KERNEL_UNLOCK();
m_freem(packet);
} else {