Author: markj
Date: Wed Dec  2 16:01:43 2020
New Revision: 368276
URL: https://svnweb.freebsd.org/changeset/base/368276

Log:
  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:  sig...@gmail.com
  Reviewed by:  kp
  MFC after:    1 week
  Sponsored by: The FreeBSD Foundation
  Differential Revision:        https://reviews.freebsd.org/D27440

Modified:
  head/sys/netpfil/pf/pf_table.c

Modified: head/sys/netpfil/pf/pf_table.c
==============================================================================
--- head/sys/netpfil/pf/pf_table.c      Wed Dec  2 15:59:08 2020        
(r368275)
+++ head/sys/netpfil/pf/pf_table.c      Wed Dec  2 16:01:43 2020        
(r368276)
@@ -1641,6 +1641,7 @@ pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket
 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 {
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to