Index | Thread | Search

From:
Carsten Beckmann <carsten_beckmann@genua.de>
Subject:
pfctl: fix resetting limits
To:
"sashan@fastmail.net" <sashan@fastmail.net>
Cc:
"tech@openbsd.org" <tech@openbsd.org>
Date:
Mon, 24 Nov 2025 13:21:10 +0000

Download raw body.

Thread
Hi,

Am Sonntag, dem 23.11.2025 um 18:57 +0100 schrieb Alexandr Nedvedicky:
> Hello,
> 
> On Wed, Nov 19, 2025 at 11:34:19AM +0000, Carsten Beckmann wrote:
> > Hi,
> > 
> > I've noticed a few issues with pfctl that are caused by this
> > change:
> > 
> > https://github.com/openbsd/src/commit/85baac77515140239632c5e733ba5c896915fadc
> > 
> > 'pfctl -F Reset' no longer resets limits back to their default
> > because they are
> > initialized with the currently active limit in pfctl_init_options
> > now.
> > 
> 
>     I agree the 'pfctl -F Reset' should set limits to defaults set at
>     compile time. However the proposed change is not quite right.
> 
>     Consider scenario as follows:
> 
>         #
>         # prepare ruleset that increases anchors limit
>         # to 1024 and then loads 640 anchors to pf(4)
>         #
>         echo 'set limit anchors 1024' > anchors.conf
>         for i in `seq 640` ; do echo "anchor \"test_$i\"" >>
> anchors.conf ; done
> 
>         #
>         # prepare a ruleset with single rule, it does not
>         # contain 'set limit...'
>         #
>         echo 'anchor "test_zero"' > one-anchor.conf
> 
>     Use pfctl(8) in current to load anchors.conf
> 
>         pfctl -f anchors.conf
>         echo $?
> 
>     then load single anchor:
> 
>         pfctl -f one-anchor.conf
>         echo $?
> 
>     both commands succeed. repeat the test with fixed pfctl
> 
>         ./pfctl -f anchors.conf
>         echo $?
> 
>         ./pfctl -f one-anchor.conf
>         echo $?
> 
>     loading one-anchor.conf fails with error:
>         pfctl: Current pool size exceeds requested anchors limit 512

I agree, my change would lead to an error in that situation. In
general this is caused by a bigger issue with pf/pfctl though: Even if
you have two perfectly valid configurations for pf you might not be
able to switch between them without an intermediary step like 'pfctl -F
rules'. For example, try this:

# echo 'set limit anchors 1024' > anchors.conf
# for i in `seq 640`; do echo "anchor \"test_$i\"" >> anchors.conf; done
# echo 'set limit anchors 512' > lower-limit.conf
# echo 'anchor "test_zero"' >> lower-limit.conf
# pfctl -f anchors.conf
# echo $?
0
# pfctl -f lower-limit.conf
pfctl: Current pool size exceeds requested anchors limit 512
pfctl: Current pool size exceeds requested anchors limit 512
# echo $?
1

It doesn't matter if you use pfctl with or without my change, loading
the second configuration directly after the first always fails. I don't
see an easy solution for that problem though.

> 
> </snip>
> 
> looking at suggested change I think changes to pfctl_init_options()
> should be reverted and the function should be left intact.
> 
> </snip>
> > +       pf->limit[PF_LIMIT_FRAGS] = mcl / 4;
> > +
> > +       pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT;
> > +       pf->limit[PF_LIMIT_TABLES] = PFR_KTABLE_HIWAT;
> > +       pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
> > +       pf->limit[PF_LIMIT_PKTDELAY_PKTS] = PF_PKTDELAY_MAXPKTS;
> > +       pf->limit[PF_LIMIT_ANCHORS] = PF_ANCHOR_HIWAT;
> >  
> 
> the changes above should go to pfctl_reset() after the call to
> pfctl_init_options() there. 

If you do this you will solve the error you mentioned above (though
also only for some configurations), but you will have the issue with
other configurations suddenly breaking after a reboot like I mentioned
in my initial email. For example, set up a configuration like this
which can be loaded without a problem:

# echo 'set limit anchors 1024' > high-limit.conf
# echo 'anchor "test_zero"' >> high-limit.conf
# pfctl -f high-limit.conf
# echo $?
0

Afterwards set up another configuration. Even though it does not
specify an increased limit for anchors it can still be loaded because
it reuses the limit from the previous configuration:

# for i in `seq 640`; do echo "anchor \"test_$i\"" >> no-limit-anchors.conf; done
# pfctl -f no-limit-anchors.conf
# echo $?
0

Now make this the default configuration and reboot:

# cp no-limit-anchors.conf /etc/pf.conf
# reboot

If you watch the /etc/rc output during reboot you will see that it
fails to load the configuration with the following error:

pfctl: DIOCADDRULE: Invalid argument

The error message is a bit misleading, but it's caused by the limit
being back to the default value after the reboot and the configuration
does not have the necessary 'set limit' option to work on its own. With
my change you would have caught that problem earlier:

# ./pfctl -f high-limit.conf
# echo $?
0
# ./pfctl -f no-limit-anchors.conf
pfctl: Current pool size exceeds requested anchors limit 512
# echo $?
1

I think unless we can somehow make loading a pf configuration truly
independent of the currently loaded configuration we have to live with
the fact that it will sometimes fail to load a valid configuration
depending on the current state. And if that's the case I would argue
that it's better to maybe reject a valid configuration that might work
later, e.g. after a 'pfctl -F rules', instead of maybe accepting an
invalid configuration that breaks after a reboot.

> 
> thanks and
> regards
> sashan
>