From 81b54c9672a05d5b452c1f848dc3ddfb2b9271ae Mon Sep 17 00:00:00 2001 From: rwatson Date: Sun, 26 Apr 2009 19:05:40 +0000 Subject: Acquire IF_ADDR_LOCK() around most iterations over ifp->if_addrhead (colloquially known as if_addrlist). Currently not acquired around interface address loops that call out to the routing code due to potential lock order issues. MFC after: 3 weeks --- sys/netinet/ip_carp.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'sys/netinet') diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 33b5059..b2922fc 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -275,6 +275,7 @@ carp_hmac_prepare(struct carp_softc *sc) found = 0; last = cur; cur.s_addr = 0xffffffff; + IF_ADDR_LOCK(SC2IFP(sc)); TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) { in.s_addr = ifatoia(ifa)->ia_addr.sin_addr.s_addr; if (ifa->ifa_addr->sa_family == AF_INET && @@ -284,6 +285,7 @@ carp_hmac_prepare(struct carp_softc *sc) found++; } } + IF_ADDR_UNLOCK(SC2IFP(sc)); if (found) SHA1Update(&sc->sc_sha1, (void *)&cur, sizeof(cur)); } while (found); @@ -294,6 +296,7 @@ carp_hmac_prepare(struct carp_softc *sc) found = 0; last6 = cur6; memset(&cur6, 0xff, sizeof(cur6)); + IF_ADDR_LOCK(SC2IFP(sc)); TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) { in6 = ifatoia6(ifa)->ia_addr.sin6_addr; if (IN6_IS_SCOPE_EMBED(&in6)) @@ -305,6 +308,7 @@ carp_hmac_prepare(struct carp_softc *sc) found++; } } + IF_ADDR_UNLOCK(SC2IFP(sc)); if (found) SHA1Update(&sc->sc_sha1, (void *)&cur6, sizeof(cur6)); } while (found); @@ -1121,6 +1125,7 @@ carp_addrcount(struct carp_if *cif, struct in_ifaddr *ia, int type) (SC2IFP(vh)->if_flags & IFF_UP) && (SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING)) || (type == CARP_COUNT_MASTER && vh->sc_state == MASTER)) { + IF_ADDR_LOCK(SC2IFP(vh)); TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family == AF_INET && @@ -1128,6 +1133,7 @@ carp_addrcount(struct carp_if *cif, struct in_ifaddr *ia, int type) ifatoia(ifa)->ia_addr.sin_addr.s_addr) count++; } + IF_ADDR_UNLOCK(SC2IFP(vh)); } } return (count); @@ -1166,6 +1172,7 @@ carp_iamatch(void *v, struct in_ifaddr *ia, TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { if ((SC2IFP(vh)->if_flags & IFF_UP) && (SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING)) { + IF_ADDR_LOCK(SC2IFP(vh)); TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family == @@ -1176,9 +1183,11 @@ carp_iamatch(void *v, struct in_ifaddr *ia, if (vh->sc_state == MASTER) { *enaddr = IF_LLADDR(vh->sc_ifp); + IF_ADDR_UNLOCK(SC2IFP(vh)); CARP_UNLOCK(cif); return (1); } else { + IF_ADDR_UNLOCK(SC2IFP(vh)); CARP_UNLOCK(cif); return (0); } @@ -1186,6 +1195,7 @@ carp_iamatch(void *v, struct in_ifaddr *ia, count++; } } + IF_ADDR_UNLOCK(SC2IFP(vh)); } } } else { @@ -1214,16 +1224,19 @@ carp_iamatch6(void *v, struct in6_addr *taddr) CARP_LOCK(cif); TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) { + IF_ADDR_LOCK(SC2IFP(vh)); TAILQ_FOREACH(ifa, &SC2IFP(vh)->if_addrlist, ifa_list) { if (IN6_ARE_ADDR_EQUAL(taddr, &ifatoia6(ifa)->ia_addr.sin6_addr) && (SC2IFP(vh)->if_flags & IFF_UP) && (SC2IFP(vh)->if_drv_flags & IFF_DRV_RUNNING) && vh->sc_state == MASTER) { + IF_ADDR_UNLOCK(SC2IFP(vh)); CARP_UNLOCK(cif); return (ifa); } } + IF_ADDR_UNLOCK(SC2IFP(vh)); } CARP_UNLOCK(cif); @@ -1240,6 +1253,7 @@ carp_macmatch6(void *v, struct mbuf *m, const struct in6_addr *taddr) CARP_LOCK(cif); TAILQ_FOREACH(sc, &cif->vhif_vrs, sc_list) { + IF_ADDR_LOCK(SC2IFP(sc)); TAILQ_FOREACH(ifa, &SC2IFP(sc)->if_addrlist, ifa_list) { if (IN6_ARE_ADDR_EQUAL(taddr, &ifatoia6(ifa)->ia_addr.sin6_addr) && @@ -1250,6 +1264,7 @@ carp_macmatch6(void *v, struct mbuf *m, const struct in6_addr *taddr) sizeof(struct ifnet *), M_NOWAIT); if (mtag == NULL) { /* better a bit than nothing */ + IF_ADDR_UNLOCK(SC2IFP(sc)); CARP_UNLOCK(cif); return (IF_LLADDR(sc->sc_ifp)); } @@ -1257,10 +1272,12 @@ carp_macmatch6(void *v, struct mbuf *m, const struct in6_addr *taddr) sizeof(struct ifnet *)); m_tag_prepend(m, mtag); + IF_ADDR_UNLOCK(SC2IFP(sc)); CARP_UNLOCK(cif); return (IF_LLADDR(sc->sc_ifp)); } } + IF_ADDR_UNLOCK(SC2IFP(sc)); } CARP_UNLOCK(cif); -- cgit v1.1