pppx_if_start() checks `IFF_RUNNING' bit to be sure `pxi' is consistent
but this bit is not cleared on `pxi' destroy. pppx_if_output() checks
`IFF_UP' bit for the same reason but this bit is always set and this
check is useless. pppac_output() checks `IFF_RUNNING' bit but
pppac_start() doesn't.

Diff below adds `IFF_RUNNING' clearing to pppx_if_destroy() before `pxi'
destruction to be sure this `pxi' can't be accessed from `ifnet' in
potencial context switch caused by if_detach().

In pppx_if_output() `IFF_RUNNING' checked instead of `IFF_UP' for
consistency with other code.

Also `IFF_RUNNING' checked in pppac_start().

Index: sys/net/if_pppx.c
===================================================================
RCS file: /cvs/src/sys/net/if_pppx.c,v
retrieving revision 1.89
diff -u -p -r1.89 if_pppx.c
--- sys/net/if_pppx.c   22 Jun 2020 10:01:03 -0000      1.89
+++ sys/net/if_pppx.c   22 Jun 2020 11:59:28 -0000
@@ -854,9 +854,10 @@ pppx_if_destroy(struct pppx_dev *pxd, st
        struct pipex_session *session;
 
        NET_ASSERT_LOCKED();
-       pxi->pxi_ready = 0;
        session = pxi->pxi_session;
        ifp = &pxi->pxi_if;
+       pxi->pxi_ready = 0;
+       CLR(ifp->if_flags, IFF_RUNNING);
 
        pipex_unlink_session(session);
 
@@ -910,7 +911,7 @@ pppx_if_output(struct ifnet *ifp, struct
 
        NET_ASSERT_LOCKED();
 
-       if (!ISSET(ifp->if_flags, IFF_UP)) {
+       if (!ISSET(ifp->if_flags, IFF_RUNNING)) {
                m_freem(m);
                error = ENETDOWN;
                goto out;
@@ -1465,6 +1466,9 @@ pppac_start(struct ifnet *ifp)
 {
        struct pppac_softc *sc = ifp->if_softc;
        struct mbuf *m;
+
+       if (!ISSET(ifp->if_flags, IFF_RUNNING))
+               return;
 
        while ((m = ifq_dequeue(&ifp->if_snd)) != NULL) {
 #if NBPFILTER > 0

Reply via email to