aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2021-05-24 06:32:16 +0000
committerKristof Provost <kp@FreeBSD.org>2021-05-27 10:09:04 +0000
commitc3e4b38f4932d0ce457508b3893324a520e0dc30 (patch)
tree7c53af340f972a747532d434d74eb900fae3a326
parent1f22359d3ff22fe919cf3965eb32ece5de1be3c1 (diff)
downloadsrc-c3e4b38f4932d0ce457508b3893324a520e0dc30.tar.gz
src-c3e4b38f4932d0ce457508b3893324a520e0dc30.zip
pf: fix ioctl() memory leak
When we create an nvlist and insert it into another nvlist we must remember to destroy it. The nvlist_add_nvlist() function makes a copy, just like nvlist_add_string() makes a copy of the string. If we don't we're leaking memory on every (nvlist-based) ioctl() call. While here remove two redundant 'break' statements. PR: 255971 MFC after: 3 days Sponsored by: Rubicon Communications, LLC ("Netgate") (cherry picked from commit 4483fb47735c29408c72045469c9c4b3e549668b)
-rw-r--r--sys/netpfil/pf/pf_ioctl.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 42429972fe53..7f72d95e3c84 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -1783,6 +1783,7 @@ pf_pool_to_nvpool(const struct pf_kpool *pool)
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "counter", tmp);
+ nvlist_destroy(tmp);
nvlist_add_number(nvl, "tblidx", pool->tblidx);
pf_uint16_array_nv(nvl, "proxy_port", pool->proxy_port, 2);
@@ -1792,6 +1793,7 @@ pf_pool_to_nvpool(const struct pf_kpool *pool)
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "mape", tmp);
+ nvlist_destroy(tmp);
return (nvl);
@@ -1863,10 +1865,12 @@ pf_addr_wrap_to_nvaddr_wrap(const struct pf_addr_wrap *addr)
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "addr", tmp);
+ nvlist_destroy(tmp);
tmp = pf_addr_to_nvaddr(&addr->v.a.mask);
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "mask", tmp);
+ nvlist_destroy(tmp);
return (nvl);
@@ -1931,6 +1935,7 @@ pf_rule_addr_to_nvrule_addr(const struct pf_rule_addr *addr)
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "addr", tmp);
+ nvlist_destroy(tmp);
pf_uint16_array_nv(nvl, "port", addr->port, 2);
nvlist_add_number(nvl, "neg", addr->neg);
nvlist_add_number(nvl, "port_op", addr->port_op);
@@ -2156,6 +2161,7 @@ pf_divert_to_nvdivert(const struct pf_krule *rule)
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "addr", tmp);
+ nvlist_destroy(tmp);
nvlist_add_number(nvl, "port", rule->divert.port);
return (nvl);
@@ -2179,10 +2185,12 @@ pf_krule_to_nvrule(const struct pf_krule *rule)
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "src", tmp);
+ nvlist_destroy(tmp);
tmp = pf_rule_addr_to_nvrule_addr(&rule->dst);
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "dst", tmp);
+ nvlist_destroy(tmp);
for (int i = 0; i < PF_SKIP_COUNT; i++) {
nvlist_append_number_array(nvl, "skip",
@@ -2204,6 +2212,7 @@ pf_krule_to_nvrule(const struct pf_krule *rule)
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "rpool", tmp);
+ nvlist_destroy(tmp);
nvlist_add_number(nvl, "evaluations",
counter_u64_fetch(rule->evaluations));
@@ -2249,10 +2258,12 @@ pf_krule_to_nvrule(const struct pf_krule *rule)
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "uid", tmp);
+ nvlist_destroy(tmp);
tmp = pf_rule_uid_to_nvrule_uid((const struct pf_rule_uid *)&rule->gid);
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "gid", tmp);
+ nvlist_destroy(tmp);
nvlist_add_number(nvl, "rule_flag", rule->rule_flag);
nvlist_add_number(nvl, "action", rule->action);
@@ -2289,6 +2300,7 @@ pf_krule_to_nvrule(const struct pf_krule *rule)
if (tmp == NULL)
goto error;
nvlist_add_nvlist(nvl, "divert", tmp);
+ nvlist_destroy(tmp);
return (nvl);
@@ -2671,6 +2683,7 @@ pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer)
if (tmp == NULL)
goto errout;
nvlist_add_nvlist(nvl, "scrub", tmp);
+ nvlist_destroy(tmp);
}
nvlist_add_number(nvl, "seqlo", peer->seqlo);
@@ -2707,26 +2720,31 @@ pf_state_to_nvstate(const struct pf_state *s)
if (tmp == NULL)
goto errout;
nvlist_add_nvlist(nvl, "stack_key", tmp);
+ nvlist_destroy(tmp);
tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]);
if (tmp == NULL)
goto errout;
nvlist_add_nvlist(nvl, "wire_key", tmp);
+ nvlist_destroy(tmp);
tmp = pf_state_peer_to_nvstate_peer(&s->src);
if (tmp == NULL)
goto errout;
nvlist_add_nvlist(nvl, "src", tmp);
+ nvlist_destroy(tmp);
tmp = pf_state_peer_to_nvstate_peer(&s->dst);
if (tmp == NULL)
goto errout;
nvlist_add_nvlist(nvl, "dst", tmp);
+ nvlist_destroy(tmp);
tmp = pf_addr_to_nvaddr(&s->rt_addr);
if (tmp == NULL)
goto errout;
nvlist_add_nvlist(nvl, "rt_addr", tmp);
+ nvlist_destroy(tmp);
nvlist_add_number(nvl, "rule", s->rule.ptr ? s->rule.ptr->nr : -1);
nvlist_add_number(nvl, "anchor",
@@ -3328,7 +3346,6 @@ DIOCADDRULENV_error:
ruleset->rules[rs_num].active.ticket) {
PF_RULES_WUNLOCK();
ERROUT(EBUSY);
- break;
}
if ((error = nvlist_error(nvl))) {
@@ -3342,7 +3359,6 @@ DIOCADDRULENV_error:
if (rule == NULL) {
PF_RULES_WUNLOCK();
ERROUT(EBUSY);
- break;
}
nvrule = pf_krule_to_nvrule(rule);
@@ -3355,6 +3371,7 @@ DIOCADDRULENV_error:
}
nvlist_add_number(nvl, "nr", nr);
nvlist_add_nvlist(nvl, "rule", nvrule);
+ nvlist_destroy(nvrule);
nvrule = NULL;
if (pf_kanchor_nvcopyout(ruleset, rule, nvl)) {
PF_RULES_WUNLOCK();
@@ -5927,6 +5944,7 @@ pf_getstate(struct pfioc_nv *nv)
ERROUT(ENOMEM);
nvlist_add_nvlist(nvl, "state", nvls);
+ nvlist_destroy(nvls);
nvlpacked = nvlist_pack(nvl, &nv->len);
if (nvlpacked == NULL)