The branch main has been updated by kp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=01194da28a2123a2aa09808319f152fa115f60f1

commit 01194da28a2123a2aa09808319f152fa115f60f1
Author:     Kristof Provost <[email protected]>
AuthorDate: 2023-03-22 13:46:25 +0000
Commit:     Kristof Provost <[email protected]>
CommitDate: 2023-03-27 23:17:55 +0000

    pfsync: hold b_mtx for callout_stop(pd_tmo)
    
    The pd_tmo callout has an associated mutex, which we must hold while
    calling callout_stop().
    
    Reported by:    markj
    Reviewed by:    markj
    MFC after:      3 days
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D39223
---
 sys/netpfil/pf/if_pfsync.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c
index ae3a2e46e26b..4e4bbc9bc8b7 100644
--- a/sys/netpfil/pf/if_pfsync.c
+++ b/sys/netpfil/pf/if_pfsync.c
@@ -402,7 +402,7 @@ pfsync_clone_destroy(struct ifnet *ifp)
 {
        struct pfsync_softc *sc = ifp->if_softc;
        struct pfsync_bucket *b;
-       int c;
+       int c, ret;
 
        for (c = 0; c < pfsync_buckets; c++) {
                b = &sc->sc_buckets[c];
@@ -411,22 +411,25 @@ pfsync_clone_destroy(struct ifnet *ifp)
                 * cleared by pfsync_uninit(), and we have only to
                 * drain callouts.
                 */
+               PFSYNC_BUCKET_LOCK(b);
                while (b->b_deferred > 0) {
                        struct pfsync_deferral *pd =
                            TAILQ_FIRST(&b->b_deferrals);
 
-                       TAILQ_REMOVE(&b->b_deferrals, pd, pd_entry);
-                       b->b_deferred--;
-                       if (callout_stop(&pd->pd_tmo) > 0) {
-                               pf_release_state(pd->pd_st);
-                               m_freem(pd->pd_m);
-                               free(pd, M_PFSYNC);
+                       ret = callout_stop(&pd->pd_tmo);
+                       PFSYNC_BUCKET_UNLOCK(b);
+                       if (ret > 0) {
+                               pfsync_undefer(pd, 1);
                        } else {
                                pd->pd_refs++;
                                callout_drain(&pd->pd_tmo);
-                               free(pd, M_PFSYNC);
                        }
+                       free(pd, M_PFSYNC);
+                       PFSYNC_BUCKET_LOCK(b);
                }
+               MPASS(b->b_deferred == 0);
+               MPASS(TAILQ_EMPTY(&b->b_deferrals));
+               PFSYNC_BUCKET_UNLOCK(b);
 
                callout_drain(&b->b_tmo);
        }

Reply via email to