On Wed, Aug 10, 2022 at 12:52:06AM +0200, Hrvoje Popovski wrote:
> On 9.8.2022. 22:22, Vitaliy Makkoveev wrote:
> > Hi,
> > 
> > The kernel lock within pflow_output_process() doesn't help because the
> > following sosend() has sleep points. So, at least pflow_clone_destroy()
> > should wait until pflow_output_process() finished. We should use
> > taskq_del_barrier(9) instead of task_del(9).
> > 
> > Also we need to unlink dying pflow(4) interface from the stack before
> > start destruction.
> > 
> > This diff should help. Please keep in mind, this diff is incomplete,
> > because it doesn't fix the race between pflowioctl() and
> > pflow_output_process(). This race is much more complicated, because we
> > need to introduce the new lock to protect `so' and take it before call
> > sosend(), but the sosend() takes netlock, which is taken before
> > pflowioctl() where we modify `so'. This introduces re-locking games to
> > pflowioctl() path, I so want to make this with separate diff, because
> > this potential panic was not triggered.
> > 
> 
> Hi,
> 
> with this diff I'm getting this protection fault trap
> 

taskq_del_barrier(9) has a bug and doesn't work as expected. This diff
uses taskq_barrier(9).

According private Hrvoje report it fixes the problem.

Index: sys/net/if_pflow.c
===================================================================
RCS file: /cvs/src/sys/net/if_pflow.c,v
retrieving revision 1.94
diff -u -p -r1.94 if_pflow.c
--- sys/net/if_pflow.c  6 Jun 2022 14:45:41 -0000       1.94
+++ sys/net/if_pflow.c  10 Aug 2022 12:26:57 -0000
@@ -274,6 +274,10 @@ pflow_clone_destroy(struct ifnet *ifp)
 
        error = 0;
 
+       NET_LOCK();
+       SLIST_REMOVE(&pflowif_list, sc, pflow_softc, sc_next);
+       NET_UNLOCK();
+
        if (timeout_initialized(&sc->sc_tmo))
                timeout_del(&sc->sc_tmo);
        if (timeout_initialized(&sc->sc_tmo6))
@@ -282,6 +286,7 @@ pflow_clone_destroy(struct ifnet *ifp)
                timeout_del(&sc->sc_tmo_tmpl);
        pflow_flush(sc);
        task_del(net_tq(ifp->if_index), &sc->sc_outputtask);
+       taskq_barrier(net_tq(ifp->if_index));
        mq_purge(&sc->sc_outputqueue);
        m_freem(sc->send_nam);
        if (sc->so != NULL) {
@@ -293,9 +298,6 @@ pflow_clone_destroy(struct ifnet *ifp)
        if (sc->sc_flowsrc != NULL)
                free(sc->sc_flowsrc, M_DEVBUF, sc->sc_flowsrc->sa_len);
        if_detach(ifp);
-       NET_LOCK();
-       SLIST_REMOVE(&pflowif_list, sc, pflow_softc, sc_next);
-       NET_UNLOCK();
        free(sc, M_DEVBUF, sizeof(*sc));
        return (error);
 }

Reply via email to