DF-3425 / fix.diff
--- a/sys/netinet/ip_encap.c +++ b/sys/netinet/ip_encap.c @@ -92,6 +92,13 @@ #include <sys/thread2.h> MALLOC_DEFINE(M_IPENCAP, "IP Encapsulation", "IP Encapsulation"); +/* + * The encaptab walk in encap4_input()/encap6_input() runs from netisr + * transport processing, i.e. with mp_token held. Mutators must take + * mp_token too so they cannot unlink+free an entry (or the caller's + * softc, via ep->arg) while a walk is in flight (DF-3425). + */ + static void encap_add (struct encaptab *); static int mask_match (const struct encaptab *, const struct sockaddr *, const struct sockaddr *); @@ -326,6 +333,7 @@ { struct encaptab *ep; + lwkt_gettoken(&mp_token); crit_enter(); /* sanity check on args */ if (sp->sa_len > sizeof ep->src || dp->sa_len > sizeof ep->dst) @@ -369,10 +377,12 @@ encap_add(ep); crit_exit(); + lwkt_reltoken(&mp_token); return ep; fail: crit_exit(); + lwkt_reltoken(&mp_token); return NULL; } @@ -383,6 +393,7 @@ { struct encaptab *ep; + lwkt_gettoken(&mp_token); crit_enter(); /* sanity check on args */ if (!func) @@ -401,10 +412,12 @@ encap_add(ep); crit_exit(); + lwkt_reltoken(&mp_token); return ep; fail: crit_exit(); + lwkt_reltoken(&mp_token); return NULL; } @@ -414,14 +427,17 @@ const struct encaptab *ep = cookie; struct encaptab *p; + lwkt_gettoken(&mp_token); for (p = LIST_FIRST(&encaptab); p; p = LIST_NEXT(p, chain)) { if (p == ep) { LIST_REMOVE(p, chain); kfree(p, M_IPENCAP); /*XXX*/ + lwkt_reltoken(&mp_token); return 0; } } + lwkt_reltoken(&mp_token); return EINVAL; } |