aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2023-03-20 13:29:55 +0000
committerKristof Provost <kp@FreeBSD.org>2023-03-27 00:28:32 +0000
commit09b7cab88f652e3a3682749e38c043d25dd7d0ed (patch)
treec583c0ac0a7043ed45bf2e09badb3a064f6777cc
parentf0cea48cb780522234370e122fdb837388b97a06 (diff)
downloadsrc-09b7cab88f652e3a3682749e38c043d25dd7d0ed.tar.gz
src-09b7cab88f652e3a3682749e38c043d25dd7d0ed.zip
pfsync: fix pfsync_undefer_state() locking
pfsync_undefer_state() takes the bucket lock, but could get called from places (e.g. from pfsync_update_state() or pfsync_delete_state()) where we already held the lock. As it can also be called from places where we don't yet hold the lock create new locked variant for use when the lock is already held. Keep using pfsync_undefer_state() where the lock must still be taken. PR: 268246 MFC after: 1 week Sponsored by: Rubicon Communications, LLC (Netgate) (cherry picked from commit 53247cdf12449e90f6736ae563e4cce8315c923f)
-rw-r--r--sys/netpfil/pf/if_pfsync.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/sys/netpfil/pf/if_pfsync.c b/sys/netpfil/pf/if_pfsync.c
index 8d90f76a3faa..6a67b8fe3d80 100644
--- a/sys/netpfil/pf/if_pfsync.c
+++ b/sys/netpfil/pf/if_pfsync.c
@@ -295,6 +295,7 @@ static int pfsyncioctl(struct ifnet *, u_long, caddr_t);
static int pfsync_defer(struct pf_kstate *, struct mbuf *);
static void pfsync_undefer(struct pfsync_deferral *, int);
+static void pfsync_undefer_state_locked(struct pf_kstate *, int);
static void pfsync_undefer_state(struct pf_kstate *, int);
static void pfsync_defer_tmo(void *);
@@ -1850,28 +1851,37 @@ pfsync_defer_tmo(void *arg)
}
static void
-pfsync_undefer_state(struct pf_kstate *st, int drop)
+pfsync_undefer_state_locked(struct pf_kstate *st, int drop)
{
struct pfsync_softc *sc = V_pfsyncif;
struct pfsync_deferral *pd;
struct pfsync_bucket *b = pfsync_get_bucket(sc, st);
- PFSYNC_BUCKET_LOCK(b);
+ PFSYNC_BUCKET_LOCK_ASSERT(b);
TAILQ_FOREACH(pd, &b->b_deferrals, pd_entry) {
if (pd->pd_st == st) {
if (callout_stop(&pd->pd_tmo) > 0)
pfsync_undefer(pd, drop);
- PFSYNC_BUCKET_UNLOCK(b);
return;
}
}
- PFSYNC_BUCKET_UNLOCK(b);
panic("%s: unable to find deferred state", __func__);
}
+static void
+pfsync_undefer_state(struct pf_kstate *st, int drop)
+{
+ struct pfsync_softc *sc = V_pfsyncif;
+ struct pfsync_bucket *b = pfsync_get_bucket(sc, st);
+
+ PFSYNC_BUCKET_LOCK(b);
+ pfsync_undefer_state_locked(st, drop);
+ PFSYNC_BUCKET_UNLOCK(b);
+}
+
static struct pfsync_bucket*
pfsync_get_bucket(struct pfsync_softc *sc, struct pf_kstate *st)
{
@@ -1890,7 +1900,7 @@ pfsync_update_state(struct pf_kstate *st)
PFSYNC_BUCKET_LOCK(b);
if (st->state_flags & PFSTATE_ACK)
- pfsync_undefer_state(st, 0);
+ pfsync_undefer_state_locked(st, 0);
if (st->state_flags & PFSTATE_NOSYNC) {
if (st->sync_state != PFSYNC_S_NONE)
pfsync_q_del(st, true, b);
@@ -2033,7 +2043,7 @@ pfsync_delete_state(struct pf_kstate *st)
PFSYNC_BUCKET_LOCK(b);
if (st->state_flags & PFSTATE_ACK)
- pfsync_undefer_state(st, 1);
+ pfsync_undefer_state_locked(st, 1);
if (st->state_flags & PFSTATE_NOSYNC) {
if (st->sync_state != PFSYNC_S_NONE)
pfsync_q_del(st, true, b);