aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2025-09-01 08:32:30 +0000
committerKristof Provost <kp@FreeBSD.org>2025-09-02 21:10:21 +0000
commit275ff85b254c1f160f965dd9dbb5801f66022eab (patch)
tree2aaf1a91eaa5145a825c74f2ccb1d461c71ea2f6
parent44cc3b2731914f94851c0e468a5fa07c5f6ca006 (diff)
pf: fix struct pf_krule_global leak
Make sure we free all of the trees we allocated when we free the ruleset. Found by 'kldunload pf' after a test run, now that the allocation is done from a pf-specific malloc type. Sponsored by: Rubicon Communications, LLC ("Netgate")
-rw-r--r--sys/net/pfvar.h1
-rw-r--r--sys/netpfil/pf/pf_ioctl.c2
-rw-r--r--sys/netpfil/pf/pf_ruleset.c6
3 files changed, 8 insertions, 1 deletions
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 79855fa84359..f73420494000 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -2614,6 +2614,7 @@ struct pf_kruleset *pf_find_kruleset(const char *);
struct pf_kruleset *pf_get_leaf_kruleset(char *, char **);
struct pf_kruleset *pf_find_or_create_kruleset(const char *);
void pf_rs_initialize(void);
+void pf_rule_tree_free(struct pf_krule_global *);
struct pf_krule *pf_krule_alloc(void);
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 934eff020074..06c40a03f575 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -1189,7 +1189,7 @@ pf_rule_tree_alloc(int flags)
return (tree);
}
-static void
+void
pf_rule_tree_free(struct pf_krule_global *tree)
{
diff --git a/sys/netpfil/pf/pf_ruleset.c b/sys/netpfil/pf/pf_ruleset.c
index 259f586fa127..1711e690f6bb 100644
--- a/sys/netpfil/pf/pf_ruleset.c
+++ b/sys/netpfil/pf/pf_ruleset.c
@@ -336,6 +336,12 @@ pf_remove_if_empty_kruleset(struct pf_kruleset *ruleset)
int i;
while (ruleset != NULL) {
+ for (int i = 0; i < PF_RULESET_MAX; i++) {
+ pf_rule_tree_free(ruleset->rules[i].active.tree);
+ ruleset->rules[i].active.tree = NULL;
+ pf_rule_tree_free(ruleset->rules[i].inactive.tree);
+ ruleset->rules[i].inactive.tree = NULL;
+ }
if (ruleset == &pf_main_ruleset ||
!RB_EMPTY(&ruleset->anchor->children) ||
ruleset->anchor->refcnt > 0 || ruleset->tables > 0 ||