diff options
author | Igor Ostapenko <pm@igoro.pro> | 2023-11-29 12:35:41 +0000 |
---|---|---|
committer | Kristof Provost <kp@FreeBSD.org> | 2023-12-06 13:23:33 +0000 |
commit | 05c55eed44e53a3a5473451d105f81ce36ef375a (patch) | |
tree | ba83b9deb9b4a1482be92a2a36c011ce777e8276 | |
parent | 3ef596c6e80562710da09c16558d7351749ea143 (diff) | |
download | src-05c55eed44e53a3a5473451d105f81ce36ef375a.tar.gz src-05c55eed44e53a3a5473451d105f81ce36ef375a.zip |
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
(cherry picked from commit 0626d30e41cba64b41667314c3a4f7611f0eb685)
-rw-r--r-- | sys/netpfil/pf/pf_ioctl.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index 639c2462fe75..81b766cb7f6a 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -5089,6 +5089,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); @@ -5499,8 +5500,34 @@ shutdown_pf(void) int error = 0; u_int32_t t[5]; char nn = '\0'; + struct pf_kanchor *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); + } + } + if ((error = pf_begin_rules(&t[0], PF_RULESET_SCRUB, &nn)) != 0) { DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: SCRUB\n")); @@ -5527,12 +5554,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; @@ -5553,6 +5584,7 @@ shutdown_pf(void) /* fingerprints and interfaces have their own cleanup code */ } while(0); +error: return (error); } |