summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2018-01-25 14:47:36 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2018-01-25 14:47:36 +0000
commitc4ca663c8aa85771ec354935314c0470d9f557c2 (patch)
tree28a0ffb39d43d5076eeae34a712524068422d41b
parent4318a51d24a39bcc62cb7a7ef6feb4082c9e923f (diff)
Use a workaround for detached parent in carp_proto_input_c().
A NULL dereference can happen since processing protocol layer is deffered to a second task. In other words the NET_LOCK() is released then regrabbed between ip_input() and carp_proto_input(). The same workaround is already in use in carp_output() due to deffered processing in case of IPsec. The real fix is to make carp(4) MP-safe and use if_get(9) there, any taker? Found & fix tested by Hrvoje Popovski.
-rw-r--r--sys/netinet/ip_carp.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index 08620190049..c18247cdd98 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_carp.c,v 1.327 2018/01/12 23:47:24 dlg Exp $ */
+/* $OpenBSD: ip_carp.c,v 1.328 2018/01/25 14:47:35 mpi Exp $ */
/*
* Copyright (c) 2002 Michael Shalayeff. All rights reserved.
@@ -601,12 +601,21 @@ carp_proto_input_c(struct ifnet *ifp, struct mbuf *m, struct carp_header *ch,
struct timeval sc_tv, ch_tv;
struct srpl *cif;
- if (ifp->if_type == IFT_CARP)
+ KERNEL_ASSERT_LOCKED(); /* touching if_carp + carp_vhosts */
+
+ if (ifp->if_type == IFT_CARP) {
+ /*
+ * If the parent of this carp(4) got destroyed while
+ * `m' was being processed, silently drop it.
+ */
+ if (ifp->if_carpdev == NULL) {
+ m_freem(m);
+ return;
+ }
cif = &ifp->if_carpdev->if_carp;
- else
+ } else
cif = &ifp->if_carp;
- KERNEL_ASSERT_LOCKED(); /* touching if_carp + carp_vhosts */
SRPL_FOREACH_LOCKED(sc, cif, sc_list) {
if (af == AF_INET &&
ismulti != IN_MULTICAST(sc->sc_peer.s_addr))