https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=296521
Bug ID: 296521
Summary: bin/pfctl: pf's netlink conversion blocks non-VNET
jails from using pfctl (no allow.pf /
RTNL_F_ALLOW_NONVNET_JAIL equivalent)
Product: Base System
Version: Unspecified
Hardware: Any
OS: Any
Status: New
Severity: Affects Some People
Priority: ---
Component: kern
Assignee: [email protected]
Reporter: [email protected]
I've upgraded from 14.4 to 15.1 and hit this. After a couple hours of
investigating an interacting on the #freebsd IRC channel, I was asked to make a
summary of what I've bumped into. This is the condensed summary of it.
Environment:
Introduced in 15.0-RELEASE, unchanged through 15.1-RELEASE and head (2026-07).
sys/netpfil/pf/pf_nl.c does not exist in 14.4; it exists in 15.0 already with
the restriction described below, so this is a 15.0 regression, not 15.1.
(Distinct from the securelevel/EPERM issue some hit after upgrading jails to
15.1 -- commit 47c12f20bf58/D56390, added between 15.0 and 15.1. That gates
on securelevel and affects VNET jails too. This report is about a separate,
unconditional gate that blocks non-VNET jails regardless of securelevel.)
Description:
15.0 converted pfctl/libpfctl from ioctl(/dev/pf) to netlink(4) (generic
netlink family "pf", sys/netpfil/pf/pf_nl.c). Every command in pf_cmds[]
sets `.cmd_priv = PRIV_NETINET_PF`, enforced unconditionally in
genl_handle_message() (sys/netlink/netlink_generic.c):
if (cmd->cmd_priv != 0 && !nlp_has_priv(nlp, cmd->cmd_priv))
return (EPERM);
prison_priv_check() (sys/kern/kern_jail.c) only grants PRIV_NETINET_PF to
jails with their own vnet (`pr_flags & PR_VNET`); there is no jail
permission that grants it to a non-VNET jail. Result: pfctl inside any
non-VNET jail now fails (EPERM) on essentially all operations -- rule
load, start/stop, tables, kill-states -- even with /dev/pf exposed via
devfs_ruleset, securelevel 0, and jailed root.
The old ioctl(/dev/pf) path (pf_ioctl.c) never called priv_check() at all;
access was gated purely by opening /dev/pf. That's why this worked
through 14.x for non-VNET jails, and why it's a regression rather than a
pre-existing restriction.
This is the same VNET-only restriction that routing sockets hit for
PRIV_NET_ROUTE -- and which *was* given a fix: commit 3a53fe2cc4b7
("jail: add allow.routing jail permission", D49843) added a
PR_ALLOW_ROUTING permission plus an RTNL_F_ALLOW_NONVNET_JAIL command
flag, checked in rtnl_handle_message() (sys/netlink/netlink_route.c), so
non-VNET jails can be opted in per command. pf's genl_cmd struct has no
equivalent flag, and no PR_ALLOW_PF exists.
How-To-Repeat:
1. Non-VNET jail, /dev/pf exposed via devfs_ruleset.
2. Inside jail: pfctl -e (or pfctl -f pf.conf)
3. Get: pfctl: DIOCSTART (or DIOCADDRULE, etc.): Operation not permitted.
4. Same command from host, or from a VNET jail: succeeds.
Suggested Fix (modeled on D49843):
- Add PR_ALLOW_PF jail permission (sys/sys/jail.h, jail.conf(5)).
- Add a command flag to struct genl_cmd (sys/netlink/netlink_ctl.h),
checked in genl_handle_message() alongside cmd_priv/cmd_securelevel, to
let PR_ALLOW_PF satisfy cmd_priv for non-VNET jails.
- Tag the relevant pf_cmds[] entries in pf_nl.c with it -- likely
everything currently gated by PRIV_NETINET_PF, restoring what non-VNET
jails could already do via the old ioctl path pre-15.0.
- Document clearly: since non-VNET jails share the host's vnet0, this
permission lets the jail rewrite the *host's* actual pf ruleset/state/
tables, not an isolated copy -- same caveat as allow.routing, worth
flagging given pf is often used for jail-facing security tooling
(e.g. fail2ban-style jails reacting to hostile input).
Workarounds in the meantime:
- Convert the jail to VNET (isolated pf instance, no gap, but requires
epair/bridge rearchitecting).
- Manage the jail's pf rules from the host instead (anchor + `pfctl -a
jailname`, or a host-side proxy acting on the jail's behalf).
- Keeping an old (14.4) pfctl binary in the jail to keep using the ioctl
path works but is unsupported/fragile and re-opens the same privilege
gap for jails handling untrusted input -- not recommended.
--
You are receiving this mail because:
You are the assignee for the bug.
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.