git: 9d9bc7f462bd - main - pf: set limits before rules
- Reply: Florian Smeets : "Re: git: 9d9bc7f462bd - main - pf: set limits before rules"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 17 Sep 2025 14:15:43 UTC
The branch main has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=9d9bc7f462bd152d87ab8f1767cad19bab09bf8b
commit 9d9bc7f462bd152d87ab8f1767cad19bab09bf8b
Author: Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-08-25 13:43:10 +0000
Commit: Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-09-17 14:15:15 +0000
pf: set limits before rules
The current way to adjust pf(4) limits in pf.conf(5) is inconvenient.
For example when ruleset uses more than 512 anchors (the current default
limit) one would typically add 'set limit anchor 1024' to adjust
the limit so the 'pf.conf(5)' gets processed. Unfortunately it
does not work because limit gets changed with DIOCXCOMMIT which
is too late. The pf.conf(5) fails to load the anchors to transaction,
because the old lower limit is still in place. To fix it we must
set the limit as soon as we parse 'set limit ...' option.
The issue has been reported and fix tested by rafal _dot_ ramocki _von_ eo.pl
OK @bluhm
Obtained from: OpenBSD, sashan <sashan@openbsd.org>, 85baac7751
Sponsored by: Rubicon Communications, LLC ("Netgate")
---
sbin/pfctl/pfctl.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 57 insertions(+), 3 deletions(-)
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 601b7651e40b..b29d992b1cda 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -110,6 +110,8 @@ int pfctl_show_status(int, int);
int pfctl_show_running(int);
int pfctl_show_timeouts(int, int);
int pfctl_show_limits(int, int);
+void pfctl_read_limits(struct pfctl_handle *);
+void pfctl_restore_limits(void);
void pfctl_debug(int, u_int32_t, int);
int pfctl_test_altqsupport(int, int);
int pfctl_show_anchors(int, int, char *);
@@ -189,6 +191,8 @@ static const struct {
{ NULL, 0 }
};
+static unsigned int limit_curr[PF_LIMIT_MAX];
+
struct pf_hint {
const char *name;
int timeout;
@@ -1780,6 +1784,31 @@ pfctl_show_limits(int dev, int opts)
return (0);
}
+void
+pfctl_read_limits(struct pfctl_handle *h)
+{
+ int i;
+
+ for (i = 0; pf_limits[i].name; i++) {
+ if (pfctl_get_limit(h, i, &limit_curr[i]))
+ err(1, "DIOCGETLIMIT");
+ }
+}
+
+void
+pfctl_restore_limits(void)
+{
+ int i;
+
+ if (pfh == NULL)
+ return;
+
+ for (i = 0; pf_limits[i].name; i++) {
+ if (pfctl_set_limit(pfh, i, limit_curr[i]))
+ warn("DIOCSETLIMIT (%s)", pf_limits[i].name);
+ }
+}
+
void
pfctl_show_creators(int opts)
{
@@ -2487,8 +2516,14 @@ pfctl_init_options(struct pfctl *pf)
pf->limit[PF_LIMIT_STATES] = PFSTATE_HIWAT;
pf->limit[PF_LIMIT_FRAGS] = PFFRAG_FRENT_HIWAT;
- pf->limit[PF_LIMIT_SRC_NODES] = PFSNODE_HIWAT;
- pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
+
+ pf->limit[PF_LIMIT_SRC_NODES] = (limit_curr[PF_LIMIT_SRC_NODES] == 0) ?
+ PFSNODE_HIWAT : limit_curr[PF_LIMIT_SRC_NODES];
+ pf->limit[PF_LIMIT_TABLE_ENTRIES] =
+ (limit_curr[PF_LIMIT_TABLE_ENTRIES] == 0) ?
+ PFR_KENTRY_HIWAT : limit_curr[PF_LIMIT_TABLE_ENTRIES];
+ pf->limit[PF_LIMIT_ANCHORS] = (limit_curr[PF_LIMIT_ANCHORS] == 0) ?
+ PF_ANCHOR_HIWAT : limit_curr[PF_LIMIT_ANCHORS];
pf->debug = PF_DEBUG_URGENT;
pf->reassemble = 0;
@@ -2589,6 +2624,9 @@ pfctl_apply_limit(struct pfctl *pf, const char *opt, unsigned int limit)
if (pf->opts & PF_OPT_VERBOSE)
printf("set limit %s %d\n", opt, limit);
+ if ((pf->opts & PF_OPT_NOACTION) == 0)
+ pfctl_load_options(pf);
+
return (0);
}
@@ -3452,6 +3490,11 @@ main(int argc, char *argv[])
if (pfh == NULL)
err(1, "Failed to open netlink");
+ if ((opts & PF_OPT_NOACTION) == 0) {
+ pfctl_read_limits(pfh);
+ atexit(pfctl_restore_limits);
+ }
+
if (opts & PF_OPT_DISABLE)
if (pfctl_disable(dev, opts))
exit_val = 1;
@@ -3695,7 +3738,18 @@ main(int argc, char *argv[])
}
}
- exit(exit_val);
+ /*
+ * prevent pfctl_restore_limits() exit handler from restoring
+ * pf(4) options settings on successful exit.
+ */
+ if (exit_val == 0) {
+ close(dev);
+ dev = -1;
+ pfctl_close(pfh);
+ pfh = NULL;
+ }
+
+ return (exit_val);
}
char *