aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2023-03-22 13:46:25 +0000
committerKristof Provost <kp@FreeBSD.org>2023-03-30 00:23:07 +0000
commit9965ab873cd7e2ff07c8052497b1d5e3ae588a27 (patch)
treee362771ecf066acfa1346e42cfea9c4ecba785df
parent738b20a47f7379b27ccf7a6d2af2c1bbfa11d05f (diff)
downloadsrc-9965ab873cd7e2ff07c8052497b1d5e3ae588a27.tar.gz
src-9965ab873cd7e2ff07c8052497b1d5e3ae588a27.zip
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 (cherry picked from commit 01194da28a2123a2aa09808319f152fa115f60f1)
-rw-r--r--sys/netpfil/pf/if_pfsync.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c
index 0a8ece621006..a05fd85423ee 100644
--- a/sys/netpfil/pf/if_pfsync.c
+++ b/sys/netpfil/pf/if_pfsync.c
@@ -395,7 +395,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];
@@ -404,22 +404,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);
}