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
 

Reply via email to