https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=298877
Bug ID: 298877
Summary: pf: netlink GETRULE drops per-rule timeouts (wrong
nested attribute type in nlattr_add_timeout)
Product: Base System
Version: 15.1-RELEASE
Hardware: Any
OS: Any
Status: New
Severity: Affects Some People
Priority: ---
Component: kern
Assignee: [email protected]
Reporter: [email protected]
CC: [email protected]
After I upgraded our first machine from 14.4 to 15.1 I noticed there is some
difference in the output of "pfctl -s rules" - missing "src.track 10". We
noticed this immediately because we compare output of live rule set with the
output of "pfctl -nvf /etc/pf.conf" as the part of the monitoring of the
machine state.
All previous versions of FreeBSD, 14.4 included has the same output but on 15.1
it's different
# pfctl -s rules | grep https
pass in on bge0 inet proto tcp from any to (bge0) port = https flags S/SA keep
state (source-track rule, max-src-conn-rate 100/10, overload <bruteforce> flush
global)
# pfctl -nvf /etc/pf.conf | grep https
pass in on bge0 inet proto tcp from any to (bge0) port = https flags S/SA keep
state (source-track rule, max-src-conn-rate 100/10, overload <bruteforce> flush
global, src.track 10)
I tried to analyze it with the help of LLM with the following result.
=============
Description:
Since FreeBSD 15.0, "pfctl -s rules" no longer shows per-rule timeout
options (e.g. "tcp.established 3600", "src.track 10"), while
"pfctl -nvf pf.conf" does. On 14.x both outputs were identical.
This includes the src.track timeout that pfctl's parser adds implicitly
to every rule with "max-src-conn-rate N/S" (timeout[PFTM_SRC_NODE] = S),
so any rule using max-src-conn-rate now prints differently in the two
commands.
The timeouts are loaded into the kernel correctly; only the read-back
path is broken.
Root cause:
sys/netpfil/pf/pf_nl.c, nlattr_add_timeout() emits the elements of the
nested PF_RT_TIMEOUT attribute with the outer attribute type:
for (int i = 0; i < PFTM_MAX; i++)
nlattr_add_u32(nw, PF_RT_TIMEOUT, timeout[i]);
Both parsers of this nested attribute expect PF_TT_TIMEOUT (1), not
PF_RT_TIMEOUT (14):
- kernel: nla_p_timeouts[] in pf_nl.c (used for ADDRULE)
- libpfctl: ap_timeouts[] in lib/libpfctl/libpfctl.c (used for GETRULE)
libpfctl's writer, snl_add_msg_attr_timeouts(), correctly uses
PF_TT_TIMEOUT, which is why rule loading works.
On GETRULE, libpfctl silently ignores the unknown type-14 attributes,
all timeouts are read back as 0, and print_rule() omits them.
Present in releng/15.0, releng/15.1, stable/15 and main.
Impact:
- Scripts comparing the loaded ruleset with "pfctl -nvf" output
report false differences after upgrading to 15.x.
- "pfctl -s rules" output is no longer a faithful representation of
the loaded ruleset; saving it and reloading it silently drops
explicit per-rule timeouts.
Proposed fix:
--- a/sys/netpfil/pf/pf_nl.c
+++ b/sys/netpfil/pf/pf_nl.c
@@ nlattr_add_timeout()
for (int i = 0; i < PFTM_MAX; i++)
- nlattr_add_u32(nw, PF_RT_TIMEOUT, timeout[i]);
+ nlattr_add_u32(nw, PF_TT_TIMEOUT, timeout[i]);
A regression test in tests/sys/netpfil/pf comparing "pfctl -sr" with
the loaded rule for a rule carrying a per-rule timeout would catch
this.
MFC to stable/15 (and an EN for 15.x) would be appreciated.
=============
I didn't test this fix yet.
--
You are receiving this mail because:
You are the assignee for the bug.