pppoe_timeout() and pppoe_clone_destroy() are both executed with kernel lock held, but they are not serialized because pppoe_timeout() has the sleep point provided by netlock. We should use timeout_del_barrier(9) to ensure pppoe_timeout() finished. Also pppoe_timeout() could be rescheduled if the interface state `sc_state' is PPPOE_STATE_PADI_SENT or PPPOE_STATE_PADR_SENT. The interface could be destroyed in any connection state, so introduce new PPPOE_STATE_DYING state and use it to prevent timeout rescheduling.
Do sppp_detach() after if_detach(). It destroys some `ifp' data, so it should be called after the interface was unlinked from the stack. Also do sppp_attach() before if_attach() call because initializes and setups `ifp' data. ok? Index: sys/net/if_pppoe.c =================================================================== RCS file: /cvs/src/sys/net/if_pppoe.c,v retrieving revision 1.81 diff -u -p -r1.81 if_pppoe.c --- sys/net/if_pppoe.c 29 Jun 2022 09:08:07 -0000 1.81 +++ sys/net/if_pppoe.c 5 Jul 2022 17:39:44 -0000 @@ -242,9 +242,9 @@ pppoe_clone_create(struct if_clone *ifc, /* init timer for interface watchdog */ timeout_set_proc(&sc->sc_timeout, pppoe_timeout, sc); + sppp_attach(&sc->sc_sppp.pp_if); if_attach(&sc->sc_sppp.pp_if); if_alloc_sadl(&sc->sc_sppp.pp_if); - sppp_attach(&sc->sc_sppp.pp_if); #if NBPFILTER > 0 bpfattach(&sc->sc_sppp.pp_if.if_bpf, &sc->sc_sppp.pp_if, DLT_PPP_ETHER, 0); #endif @@ -269,13 +269,14 @@ pppoe_clone_destroy(struct ifnet *ifp) struct pppoe_softc *sc = ifp->if_softc; NET_LOCK(); + sc->sc_state = PPPOE_STATE_DYING; LIST_REMOVE(sc, sc_list); NET_UNLOCK(); - timeout_del(&sc->sc_timeout); - - sppp_detach(&sc->sc_sppp.pp_if); if_detach(ifp); + sppp_detach(&sc->sc_sppp.pp_if); + + timeout_del_barrier(&sc->sc_timeout); if (sc->sc_concentrator_name) free(sc->sc_concentrator_name, M_DEVBUF, Index: sys/net/if_pppoe.h =================================================================== RCS file: /cvs/src/sys/net/if_pppoe.h,v retrieving revision 1.8 diff -u -p -r1.8 if_pppoe.h --- sys/net/if_pppoe.h 29 Jun 2022 09:08:07 -0000 1.8 +++ sys/net/if_pppoe.h 5 Jul 2022 17:39:44 -0000 @@ -49,6 +49,7 @@ struct pppoediscparms { #define PPPOE_STATE_PADR_SENT 2 #define PPPOE_STATE_SESSION 3 #define PPPOE_STATE_CLOSING 4 +#define PPPOE_STATE_DYING 5 /* passive */ #define PPPOE_STATE_PADO_SENT 1