pf: fix mem leaks upon vnet destroy

Add missing cleanup actions:
- remove user defined anchor rulesets
- remove user defined ether anchor rulesets
- remove tables linked to user defined anchors
- deal with wildcard anchor peculiarities to get them removed correctly

PR:		274310
Reviewed by:	kp
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D42747
This commit is contained in:
Igor Ostapenko 2023-11-29 13:35:41 +01:00 committed by Kristof Provost
parent 5c0dac0b7a
commit 0626d30e41
1 changed files with 60 additions and 7 deletions

View File

@ -5809,6 +5809,7 @@ pf_clear_tables(void)
int error;
bzero(&io, sizeof(io));
io.pfrio_flags |= PFR_FLAG_ALLRSETS;
error = pfr_clr_tables(&io.pfrio_table, &io.pfrio_ndel,
io.pfrio_flags);
@ -6219,8 +6220,54 @@ shutdown_pf(void)
int error = 0;
u_int32_t t[5];
char nn = '\0';
struct pf_kanchor *anchor;
struct pf_keth_anchor *eth_anchor;
int rs_num;
do {
/* Unlink rules of all user defined anchors */
RB_FOREACH(anchor, pf_kanchor_global, &V_pf_anchors) {
/* Wildcard based anchors may not have a respective
* explicit anchor rule or they may be left empty
* without rules. It leads to anchor.refcnt=0, and the
* rest of the logic does not expect it. */
if (anchor->refcnt == 0)
anchor->refcnt = 1;
for (rs_num = 0; rs_num < PF_RULESET_MAX; ++rs_num) {
if ((error = pf_begin_rules(&t[rs_num], rs_num,
anchor->path)) != 0) {
DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: "
"anchor.path=%s rs_num=%d\n",
anchor->path, rs_num));
goto error; /* XXX: rollback? */
}
}
for (rs_num = 0; rs_num < PF_RULESET_MAX; ++rs_num) {
error = pf_commit_rules(t[rs_num], rs_num,
anchor->path);
MPASS(error == 0);
}
}
/* Unlink rules of all user defined ether anchors */
RB_FOREACH(eth_anchor, pf_keth_anchor_global,
&V_pf_keth_anchors) {
/* Wildcard based anchors may not have a respective
* explicit anchor rule or they may be left empty
* without rules. It leads to anchor.refcnt=0, and the
* rest of the logic does not expect it. */
if (eth_anchor->refcnt == 0)
eth_anchor->refcnt = 1;
if ((error = pf_begin_eth(&t[0], eth_anchor->path))
!= 0) {
DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: eth "
"anchor.path=%s\n", eth_anchor->path));
goto error;
}
error = pf_commit_eth(t[0], eth_anchor->path);
MPASS(error == 0);
}
if ((error = pf_begin_rules(&t[0], PF_RULESET_SCRUB, &nn))
!= 0) {
DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: SCRUB\n"));
@ -6247,12 +6294,16 @@ shutdown_pf(void)
break; /* XXX: rollback? */
}
/* XXX: these should always succeed here */
pf_commit_rules(t[0], PF_RULESET_SCRUB, &nn);
pf_commit_rules(t[1], PF_RULESET_FILTER, &nn);
pf_commit_rules(t[2], PF_RULESET_NAT, &nn);
pf_commit_rules(t[3], PF_RULESET_BINAT, &nn);
pf_commit_rules(t[4], PF_RULESET_RDR, &nn);
error = pf_commit_rules(t[0], PF_RULESET_SCRUB, &nn);
MPASS(error == 0);
error = pf_commit_rules(t[1], PF_RULESET_FILTER, &nn);
MPASS(error == 0);
error = pf_commit_rules(t[2], PF_RULESET_NAT, &nn);
MPASS(error == 0);
error = pf_commit_rules(t[3], PF_RULESET_BINAT, &nn);
MPASS(error == 0);
error = pf_commit_rules(t[4], PF_RULESET_RDR, &nn);
MPASS(error == 0);
if ((error = pf_clear_tables()) != 0)
break;
@ -6261,7 +6312,8 @@ shutdown_pf(void)
DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: eth\n"));
break;
}
pf_commit_eth(t[0], &nn);
error = pf_commit_eth(t[0], &nn);
MPASS(error == 0);
#ifdef ALTQ
if ((error = pf_begin_altq(&t[0])) != 0) {
@ -6279,6 +6331,7 @@ shutdown_pf(void)
/* fingerprints and interfaces have their own cleanup code */
} while(0);
error:
return (error);
}