git: 3c87acbd4271 - stable/14 - pf: modify pfik_flags atomically

From: R. Christian McDonald <rcm_at_FreeBSD.org>
Date: Wed, 28 Oct 2026 20:41:28 UTC
The branch stable/14 has been updated by rcm:

URL: https://cgit.FreeBSD.org/src/commit/?id=3c87acbd427149450db9a800ef5a467272710709

commit 3c87acbd427149450db9a800ef5a467272710709
Author:     R. Christian McDonald <rcm@FreeBSD.org>
AuthorDate: 2026-09-30 22:56:22 +0000
Commit:     R. Christian McDonald <rcm@FreeBSD.org>
CommitDate: 2026-10-28 20:38:03 +0000

    pf: modify pfik_flags atomically
    
    The purge thread sets PFI_IFLAG_REFS on the interfaces that states
    refer to without the rules lock, under which the other flags are
    changed. The updates can interleave, so that a "set skip on" is lost,
    or outlives its removal, until the next ruleset load.
    
    Use atomic operations to modify the flags. In the purge thread, only
    write if the flag is not already set.
    
    Reviewed by:            kp
    Approved by:            kp (mentor)
    MFC after:              1 week
    Sponsored by:           Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D60107
    
    (cherry picked from commit c1241c6e30c792fb514f4689d2ed92ee21d3cf39)
---
 sys/netpfil/pf/pf.c    | 12 ++++++++++--
 sys/netpfil/pf/pf_if.c | 10 +++++-----
 2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 469087a040e1..7c1f43a8b9bd 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -2459,6 +2459,14 @@ pf_free_state(struct pf_kstate *cur)
 	pf_counter_u64_add(&V_pf_status.fcounters[FCNT_STATE_REMOVALS], 1);
 }
 
+static inline void
+pf_kkif_mark(struct pfi_kkif *kif)
+{
+
+	if ((atomic_load_int(&kif->pfik_flags) & PFI_IFLAG_REFS) == 0)
+		atomic_set_int(&kif->pfik_flags, PFI_IFLAG_REFS);
+}
+
 /*
  * Called only from pf_purge_thread(), thus serialized.
  */
@@ -2494,11 +2502,11 @@ relock:
 					s->nat_rule.ptr->rule_ref |= PFRULE_REFS;
 				if (s->anchor.ptr != NULL)
 					s->anchor.ptr->rule_ref |= PFRULE_REFS;
-				s->kif->pfik_flags |= PFI_IFLAG_REFS;
+				pf_kkif_mark(s->kif);
 				SLIST_FOREACH(mrm, &s->match_rules, entry)
 					mrm->r->rule_ref |= PFRULE_REFS;
 				if (s->rt_kif)
-					s->rt_kif->pfik_flags |= PFI_IFLAG_REFS;
+					pf_kkif_mark(s->rt_kif);
 				count++;
 			}
 			PF_HASHROW_UNLOCK(ih);
diff --git a/sys/netpfil/pf/pf_if.c b/sys/netpfil/pf/pf_if.c
index a5f26b5624bd..0de8013335f0 100644
--- a/sys/netpfil/pf/pf_if.c
+++ b/sys/netpfil/pf/pf_if.c
@@ -380,7 +380,7 @@ pfi_kkif_remove_if_unref(struct pfi_kkif *kif)
 
 	RB_REMOVE(pfi_ifhead, &V_pfi_ifs, kif);
 
-	kif->pfik_flags |= PFI_IFLAG_REFS;
+	atomic_set_int(&kif->pfik_flags, PFI_IFLAG_REFS);
 
 	mtx_lock(&pfi_unlnkdkifs_mtx);
 	LIST_INSERT_HEAD(&V_pfi_unlinked_kifs, kif, pfik_list);
@@ -414,7 +414,7 @@ pfi_kkif_purge(void)
 			LIST_REMOVE(kif, pfik_list);
 			pf_kkif_free(kif);
 		} else
-			kif->pfik_flags &= ~PFI_IFLAG_REFS;
+			atomic_clear_int(&kif->pfik_flags, PFI_IFLAG_REFS);
 	}
 	mtx_unlock(&pfi_unlnkdkifs_mtx);
 }
@@ -603,7 +603,7 @@ pfi_kkif_update(struct pfi_kkif *kif)
 			if (tmpkif == NULL)
 				continue;
 
-			tmpkif->pfik_flags |= kif->pfik_flags;
+			atomic_set_int(&tmpkif->pfik_flags, kif->pfik_flags);
 		}
 	}
 
@@ -959,7 +959,7 @@ pfi_set_flags(const char *name, int flags)
 	RB_FOREACH(p, pfi_ifhead, &V_pfi_ifs) {
 		if (pfi_skip_if(name, p))
 			continue;
-		p->pfik_flags |= flags;
+		atomic_set_int(&p->pfik_flags, flags);
 	}
 	NET_EPOCH_EXIT(et);
 	return (0);
@@ -975,7 +975,7 @@ pfi_clear_flags(const char *name, int flags)
 	RB_FOREACH_SAFE(p, pfi_ifhead, &V_pfi_ifs, tmp) {
 		if (pfi_skip_if(name, p))
 			continue;
-		p->pfik_flags &= ~flags;
+		atomic_clear_int(&p->pfik_flags, flags);
 
 		if (p->pfik_ifp == NULL && p->pfik_group == NULL &&
 		    p->pfik_flags == 0 && p->pfik_rulerefs == 0) {