diff options
author | 2017-11-13 17:00:14 +0000 | |
---|---|---|
committer | 2017-11-13 17:00:14 +0000 | |
commit | a9da2a57a80821076d90850a03f911db31b8feb0 (patch) | |
tree | 9a17fff6d4c5767896b0e6c7f3c375337838530d | |
parent | Remove useless comment about if_ioctl() & reduce grep noise. (diff) | |
download | wireguard-openbsd-a9da2a57a80821076d90850a03f911db31b8feb0.tar.xz wireguard-openbsd-a9da2a57a80821076d90850a03f911db31b8feb0.zip |
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.c | 17 |
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 { |