git: b70fadca623f - main - pf: fix dealing with 0 limits
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 08 May 2025 13:10:44 UTC
The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=b70fadca623f1ce62c34c67270feae6cf48ca4ba commit b70fadca623f1ce62c34c67270feae6cf48ca4ba Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2025-05-07 08:43:14 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2025-05-08 13:10:25 +0000 pf: fix dealing with 0 limits uma doesn't like setting a limit on a zone which previously had none. At startup pf applies the default limit to all zones, so we can assume a limit was always set. We cope with the uma limitation by translating a limit of '0' (i.e. unlimited) to INT_MAX. This is high enough that we'll never realistically hit this limit, but it keeps uma happy. Add a test case to provoke this, and while we're here also fix syncookie handling of a 0 state limit. See also: d53927b0bae45 Reported-by: syzbot+02b784f183f79d4c07e4@syzkaller.appspotmail.com Sponsored by: Rubicon Communications, LLC ("Netgate") --- lib/libpfctl/libpfctl.c | 6 +++++ sys/netpfil/pf/pf_ioctl.c | 3 ++- tests/sys/netpfil/pf/limits.sh | 53 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index 271fb33babfe..a4afa26f0afe 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -2271,6 +2271,9 @@ pfctl_set_syncookies(int dev, const struct pfctl_syncookies *s) if (ret != 0) return (ret); + if (state_limit == 0) + state_limit = INT_MAX; + lim = state_limit; hi = lim * s->highwater / 100; lo = lim * s->lowwater / 100; @@ -2311,6 +2314,9 @@ pfctl_get_syncookies(int dev, struct pfctl_syncookies *s) if (ret != 0) return (ret); + if (state_limit == 0) + state_limit = INT_MAX; + bzero(s, sizeof(*s)); nvl = nvlist_create(0); diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index 5c3aec906b79..bd3c2b93c954 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -2537,7 +2537,8 @@ pf_ioctl_set_limit(int index, unsigned int limit, unsigned int *old_limit) PF_RULES_WUNLOCK(); return (EINVAL); } - uma_zone_set_max(V_pf_limits[index].zone, limit); + uma_zone_set_max(V_pf_limits[index].zone, + limit == 0 ? INT_MAX : limit); if (old_limit != NULL) *old_limit = V_pf_limits[index].limit; V_pf_limits[index].limit = limit; diff --git a/tests/sys/netpfil/pf/limits.sh b/tests/sys/netpfil/pf/limits.sh index 474684bef660..69f0b6af2ccf 100644 --- a/tests/sys/netpfil/pf/limits.sh +++ b/tests/sys/netpfil/pf/limits.sh @@ -60,7 +60,60 @@ basic_cleanup() pft_cleanup } +atf_test_case "zero" "cleanup" +zero_head() +{ + atf_set descr 'Test changing a limit from zero on an in-use zone' + atf_set require.user root +} + +zero_body() +{ + pft_init + + epair=$(vnet_mkepair) + ifconfig ${epair}b 192.0.2.2/24 up + + vnet_mkjail alcatraz ${epair}a + jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up + + atf_check -s exit:0 -o ignore \ + ping -c 3 192.0.2.1 + + jexec alcatraz pfctl -e + # Set no limit + pft_set_rules noflush alcatraz \ + "set limit states 0" \ + "pass" + + # Check that we really report no limit + atf_check -s exit:0 -o 'match:states hard limit 0' \ + jexec alcatraz pfctl -sa + + # Create a state + atf_check -s exit:0 -o ignore \ + ping -c 3 192.0.2.1 + + # Limit states + pft_set_rules noflush alcatraz \ + "set limit states 1000" \ + "pass" + + # And create a new state + atf_check -s exit:0 -o ignore \ + ping -c 3 192.0.2.1 + + atf_check -s exit:0 -o 'match:states hard limit 1000' \ + jexec alcatraz pfctl -sa +} + +zero_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "basic" + atf_add_test_case "zero" }