aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/ip_carp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/ip_carp.c')
-rw-r--r--sys/netinet/ip_carp.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index 0ead7149c1e2..d3d7957cf087 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -206,8 +206,6 @@ struct carpkreq {
*
* Known issues with locking:
*
- * - Sending ad, we put the pointer to the softc in an mtag, and no reference
- * counting is done on the softc.
* - On module unload we may race (?) with packet processing thread
* dereferencing our function pointers.
*/
@@ -1688,6 +1686,7 @@ char *
carp_macmatch6(struct ifnet *ifp, struct mbuf *m, const struct in6_addr *taddr)
{
struct ifaddr *ifa;
+ char *mac = NULL;
NET_EPOCH_ASSERT();
@@ -1698,18 +1697,26 @@ carp_macmatch6(struct ifnet *ifp, struct mbuf *m, const struct in6_addr *taddr)
struct m_tag *mtag;
mtag = m_tag_get(PACKET_TAG_CARP,
- sizeof(struct carp_softc *), M_NOWAIT);
- if (mtag == NULL)
- /* Better a bit than nothing. */
- return (sc->sc_addr);
+ sizeof(sc->sc_vhid) + sizeof(sc->sc_addr),
+ M_NOWAIT);
+ if (mtag == NULL) {
+ CARPSTATS_INC(carps_onomem);
+ break;
+ }
+ /* carp_output expects sc_vhid first. */
+ bcopy(&sc->sc_vhid, mtag + 1, sizeof(sc->sc_vhid));
+ /*
+ * Save sc_addr into mtag data after sc_vhid to avoid
+ * possible access to destroyed softc.
+ */
+ mac = (char *)(mtag + 1) + sizeof(sc->sc_vhid);
+ bcopy(sc->sc_addr, mac, sizeof(sc->sc_addr));
- bcopy(&sc, mtag + 1, sizeof(sc));
m_tag_prepend(m, mtag);
-
- return (sc->sc_addr);
+ break;
}
- return (NULL);
+ return (mac);
}
#endif /* INET6 */