--- a/sys/net/gif/if_gif.c +++ b/sys/net/gif/if_gif.c @@ -178,6 +178,22 @@ struct gif_softc *sc = ifp->if_softc; int err; + /* + * Take the gif's ifnet serializer before tearing the softc state + * down. gif_output() holds this serializer (via + * ifsq_serialize_hw(), which is ifp->if_serializer, if.c:642) for + * the WHOLE encapsulation including the gif_psrc re-read at the + * AF dispatch, and the SIOCSIFPHYADDR/SIOCDIFPHYADDR ioctl paths + * already run under ifnet_serialize_all() (if.c:2350-2352). + * Without this, `ifconfig gifN destroy` racing in-flight traffic + * frees/NULLs gif_psrc & gif_pdst between gif_output_serialized()'s + * NULL guard (if_gif.c:345-350) and its deref at :373 (and + * between in_gif_output()'s pointer load at in_gif.c:101-102 and + * its last use), panicking the kernel (DF-3457). + * + * Nothing below takes ifp's serializer, so there is no recursion. + */ + ifnet_serialize_all(ifp); gif_delete_tunnel(&sc->gif_if); LIST_REMOVE(sc, gif_list); #ifdef INET6 @@ -193,6 +209,7 @@ } #endif gif_clear_cache(sc); + ifnet_deserialize_all(ifp); bpfdetach(ifp); if_detach(ifp);