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