From e6aed06fdfa8b1106ff4b4b1fdb60c7b46358688 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 2 Dec 2020 16:01:43 +0000 Subject: [PATCH] pf: Fix table entry counter toggling When updating a table, pf will keep existing table entry structures corresponding to addresses that are in both of the old and new tables. However, the update may also enable or disable per-entry counters which are allocated separately. Thus when toggling PFR_TFLAG_COUNTERS, the entries may be missing counters or may have unused counters allocated. Fix the problem by modifying pfr_ina_commit() to transfer counters from or to entries in the shadow table. PR: 251414 Reported by: sigsys@gmail.com Reviewed by: kp MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D27440 --- sys/netpfil/pf/pf_table.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/netpfil/pf/pf_table.c b/sys/netpfil/pf/pf_table.c index 192b5e37c77..92d9df5f189 100644 --- a/sys/netpfil/pf/pf_table.c +++ b/sys/netpfil/pf/pf_table.c @@ -1641,6 +1641,7 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd, static void pfr_commit_ktable(struct pfr_ktable *kt, long tzero) { + counter_u64_t *pkc, *qkc; struct pfr_ktable *shadow = kt->pfrkt_shadow; int nflags; @@ -1662,14 +1663,17 @@ pfr_commit_ktable(struct pfr_ktable *kt, long tzero) SLIST_INIT(&delq); SLIST_INIT(&garbageq); pfr_clean_node_mask(shadow, &addrq); - for (p = SLIST_FIRST(&addrq); p != NULL; p = next) { - next = SLIST_NEXT(p, pfrke_workq); /* XXX */ + SLIST_FOREACH_SAFE(p, &addrq, pfrke_workq, next) { pfr_copyout_addr(&ad, p); q = pfr_lookup_addr(kt, &ad, 1); if (q != NULL) { if (q->pfrke_not != p->pfrke_not) SLIST_INSERT_HEAD(&changeq, q, pfrke_workq); + pkc = &p->pfrke_counters.pfrkc_counters; + qkc = &q->pfrke_counters.pfrkc_counters; + if ((*pkc == NULL) != (*qkc == NULL)) + SWAP(counter_u64_t, *pkc, *qkc); q->pfrke_mark = 1; SLIST_INSERT_HEAD(&garbageq, p, pfrke_workq); } else {