git: 395b8ad1751b - stable/15 - pf: take the rules read lock in pf_handle_getrule()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 28 Oct 2026 20:35:42 UTC
The branch stable/15 has been updated by rcm:
URL: https://cgit.FreeBSD.org/src/commit/?id=395b8ad1751b9b8414bf2f8a692c7e79ac2a1e6a
commit 395b8ad1751b9b8414bf2f8a692c7e79ac2a1e6a
Author: R. Christian McDonald <rcm@FreeBSD.org>
AuthorDate: 2026-09-30 23:33:43 +0000
Commit: R. Christian McDonald <rcm@FreeBSD.org>
CommitDate: 2026-10-28 20:34:05 +0000
pf: take the rules read lock in pf_handle_getrule()
pfctl -sr calls PFNL_CMD_GETRULE once per rule, and
pf_handle_getrule() takes the rules write lock each time, so listing a
ruleset of N rules stops packet processing N times. Only zeroing the
counters (pfctl -z) needs the write lock. Take the read lock
otherwise, as DIOCGETRULENV does.
Reviewed by: kp
Approved by: kp (mentor)
Fixes: 777a4702c591 ("pf: implement addrule via netlink")
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D60161
(cherry picked from commit 6d7f0162bd5d25919cc18119a6e5a371acb2cf78)
---
sys/netpfil/pf/pf_nl.c | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c
index cfed37fdba80..d0c10a165969 100644
--- a/sys/netpfil/pf/pf_nl.c
+++ b/sys/netpfil/pf/pf_nl.c
@@ -884,6 +884,17 @@ pf_handle_getrule(struct nlmsghdr *hdr, struct nl_pstate *npt)
u_int64_t src_nodes_total = 0;
int rs_num;
int error;
+ PF_RULES_RLOCK_TRACKER;
+
+/* The write lock to clear counters, the read lock to only read them. */
+#define PF_GETRULE_LOCKOP(op) do { \
+ if (attrs.clear) \
+ PF_RULES_W##op(); \
+ else \
+ PF_RULES_R##op(); \
+} while (0)
+#define PF_GETRULE_LOCK() PF_GETRULE_LOCKOP(LOCK)
+#define PF_GETRULE_UNLOCK() PF_GETRULE_LOCKOP(UNLOCK)
error = nl_parse_nlmsg(hdr, &getrule_parser, npt, &attrs);
if (error != 0)
@@ -897,23 +908,23 @@ pf_handle_getrule(struct nlmsghdr *hdr, struct nl_pstate *npt)
ghdr_new->version = 0;
ghdr_new->reserved = 0;
- PF_RULES_WLOCK();
+ PF_GETRULE_LOCK();
ruleset = pf_find_kruleset(attrs.anchor);
if (ruleset == NULL) {
- PF_RULES_WUNLOCK();
+ PF_GETRULE_UNLOCK();
error = ENOENT;
goto out;
}
rs_num = pf_get_ruleset_number(attrs.action);
if (rs_num >= PF_RULESET_MAX) {
- PF_RULES_WUNLOCK();
+ PF_GETRULE_UNLOCK();
error = EINVAL;
goto out;
}
if (attrs.ticket != ruleset->rules[rs_num].active.ticket) {
- PF_RULES_WUNLOCK();
+ PF_GETRULE_UNLOCK();
error = EBUSY;
goto out;
}
@@ -922,7 +933,7 @@ pf_handle_getrule(struct nlmsghdr *hdr, struct nl_pstate *npt)
while ((rule != NULL) && (rule->nr != attrs.nr))
rule = TAILQ_NEXT(rule, entries);
if (rule == NULL) {
- PF_RULES_WUNLOCK();
+ PF_GETRULE_UNLOCK();
error = EBUSY;
goto out;
}
@@ -1034,7 +1045,10 @@ pf_handle_getrule(struct nlmsghdr *hdr, struct nl_pstate *npt)
if (attrs.clear)
pf_krule_clear_counters(rule);
- PF_RULES_WUNLOCK();
+ PF_GETRULE_UNLOCK();
+#undef PF_GETRULE_LOCKOP
+#undef PF_GETRULE_LOCK
+#undef PF_GETRULE_UNLOCK
if (!nlmsg_end(nw)) {
error = ENOMEM;