--- a/sys/dev/netif/ix/if_ix.c +++ b/sys/dev/netif/ix/if_ix.c @@ -695,6 +695,20 @@ } callout_terminate(&sc->fw_timer); + /* + * ix_txgc_timer() re-arms itself every tick (if_ix.c:373); a mere + * callout_stop() in ix_stop() cannot prevent an in-flight callback + * from re-arming after we stop it, and the re-armed callout would + * fire on tx_rings after ix_free_rings() below (use-after-free). + * callout_terminate() disarms AND waits for any running callback. + */ + if (sc->tx_rings != NULL) { + int t; + + for (t = 0; t < sc->tx_ring_cnt; ++t) + callout_terminate(&sc->tx_rings[t].tx_gc_timer); + } + if (sc->mem_res != NULL) { uint32_t ctrl_ext;