diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2017-11-13 17:00:15 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2017-11-13 17:00:15 +0000 |
commit | 1d4caf6d1b91d1ea98aef189ed3d31f2179882c3 (patch) | |
tree | 50b7ca2baddfdee5be293e4d8023bf63ce47de94 | |
parent | 0542bf745efc81d71934e43e5316fee595807eff (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.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 { |