PF pfctl: DIOCADDRULE: Operation not permitted when # pfctl -f /etc/pf.conf @ 15.1-RELEASE

Original from Thread 103052

Hi All

I'm upgraded base system with 15.1-RELEASE
I tried to reload pf() rules by # pfctl -f /etc/pf.conf
But I got
Code:
pfctl: DIOCADDRULE: Operation not permitted
/var/log/message haven't any new message.

And got security/py-fail2ban update table failed as follows.
Code:
2026-07-06 09:21:21,887 fail2ban.utils          [83696]: ERROR   19dcc6829230 -- exec: /usr/bin/xargs -I $ /sbin/pfctl -a f2b/'apache-noscript' -t 'f2b'-'apache-noscript' -T add $
2026-07-06 09:21:21,887 fail2ban.utils          [83696]: ERROR   19dcc6829230 -- stderr: 'pfctl: No error: 0'
2026-07-06 09:21:21,887 fail2ban.utils          [83696]: ERROR   19dcc6829230 -- stderr: 'xargs: /sbin/pfctl: exited with status 255; aborting'
2026-07-06 09:21:21,887 fail2ban.utils          [83696]: ERROR   19dcc6829230 -- returned 1

Content of /etc/rc.conf.d/securelevel
Code:
kern_securelevel_enable="YES"
kern_securelevel="2"

I assume the problem is bug because 15.0-RELEASE had not the problem I remember and 15.1-RELEASE release notes have not change about pf().
Or my missed something?

I found similar report PR 291981, it start from 15.0-RELEASE and status is open still:-/

Could all please help me with this problem?😺
Thanks
 
Well, securelevel 2 prevents pf rules from being modified.
Hi loveydovey

But latest securelevel() written firewall limitation only securelevel 3? :-/
Code:
2     Highly secure mode - same as secure mode, plus disks may  not  be
     opened  for  writing (except by mount(2)) whether mounted or not.
     This level    precludes tampering with file  systems    by  unmounting
     them,  but     also  inhibits     running  newfs(8) while the system is
     multi-user.
     In    addition, kernel time changes are restricted to    less  than  or
     equal  to    one  second.  Attempts to change the time by more than
     this will log the message "Time adjustment    clamped    to +1 second".

3     Network secure mode - same as highly secure mode, plus IP    packet
     filter  rules (see    ipfw(8), ipfirewall(4) and pfctl(8)) cannot be
     changed and dummynet(4) or     pf(4)    configuration  cannot  be  ad-
     justed.

Thanks you.
 
AI says:

Practical options right now

  1. Drop to kern_securelevel="1" — restores pf rule changes, but loses the securelevel-2 protections (disk write immutability, etc.). This is what others have confirmed works as a stopgap.
  2. Load your full pf ruleset (including fail2ban's anchors) before securelevel is raised, and avoid any runtime reload — not practical for fail2ban since it needs to add/remove table entries continuously, so this doesn't really solve your case.
  3. Wait for a fix — since this looks unintentional (no release-note mention, breaks documented securelevel semantics), it's likely to get corrected; keep an eye on the PR and D56390's review thread on Phabricator for the actual disposition (revert vs. intentional-but-undocumented change).

Given fail2ban needs live table updates, option 1 (securelevel 1) is the only real functional workaround until upstream resolves this.
 
"pf is documented as only blocking some calls from level 2" (referring to securelevel 2). And also there've been some changes, it seems like:
I notice this change existed in 15.1-RELEASE source code.
And section of keyword of my problem @ /usr/src/sys/netpfil/pf/pf_nl.c
Code:
.cmd_num = PFNL_CMD_ADDRULE,
.cmd_name = "ADDRULE",
.cmd_cb = pf_handle_addrule,
.cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL,
.cmd_priv = PRIV_NETINET_PF,
.cmd_securelevel = 2,

New patched cmd_securelevel = 2 is interest, does it mean execute # pfctl -f /etc/pf.conf only for kern.securelevel lower than 2?
If true, it different with securelevel() :-/
 
AI says:

Practical options right now

  1. Drop to kern_securelevel="1" — restores pf rule changes, but loses the securelevel-2 protections (disk write immutability, etc.). This is what others have confirmed works as a stopgap.
  2. Load your full pf ruleset (including fail2ban's anchors) before securelevel is raised, and avoid any runtime reload — not practical for fail2ban since it needs to add/remove table entries continuously, so this doesn't really solve your case.
  3. Wait for a fix — since this looks unintentional (no release-note mention, breaks documented securelevel semantics), it's likely to get corrected; keep an eye on the PR and D56390's review thread on Phabricator for the actual disposition (revert vs. intentional-but-undocumented change).

Given fail2ban needs live table updates, option 1 (securelevel 1) is the only real functional workaround until upstream resolves this.
Hi loveydovey

Yes, I'm workaround to drop to kern_securelevel="1" and waiting update.😺

Thanks you a lot.😺
 
Back
Top