diff options
author | Phil Sutter <phil@nwl.cc> | 2020-05-04 19:30:29 +0200 |
---|---|---|
committer | Phil Sutter <phil@nwl.cc> | 2020-05-11 14:28:29 +0200 |
commit | 5fdb447fdfe877bd6236830b4a2507d4d61bc1a1 (patch) | |
tree | a8d83c947d620c99e3a3abb97361d501371167f4 | |
parent | 196401937d76f990ad59a4a93cd5a45e91a2b12a (diff) |
nft: Fix leaks in ebt_add_policy_rule()
The function leaked memory allocated in temporary struct
iptables_command_state, clean it immediately after use.
In any of the udata-related error cases, allocated nftnl_rule would
leak, fix this by introducing a common error path to goto.
In regular code path, the allocated nftnl_rule would still leak:
batch_obj_del() does not free rules in NFT_COMPAT_RULE_APPEND jobs, as
they typically sit in cache as well. Policy rules in turn weren't added
to cache: They are created immediately before commit and never
referenced from other rules. Add them now so they are freed just like
regular rules.
Fixes: aff1162b3e4b7 ("ebtables-nft: Support user-defined chain policies")
Signed-off-by: Phil Sutter <phil@nwl.cc>
-rw-r--r-- | iptables/nft.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/iptables/nft.c b/iptables/nft.c index addde1b5..c0b5e2fc 100644 --- a/iptables/nft.c +++ b/iptables/nft.c @@ -2970,27 +2970,33 @@ static int ebt_add_policy_rule(struct nftnl_chain *c, void *data) r = nft_rule_new(h, nftnl_chain_get_str(c, NFTNL_CHAIN_NAME), nftnl_chain_get_str(c, NFTNL_CHAIN_TABLE), &cs); + ebt_cs_clean(&cs); + if (!r) return -1; udata = nftnl_udata_buf_alloc(NFT_USERDATA_MAXLEN); if (!udata) - return -1; + goto err_free_rule; if (!nftnl_udata_put_u32(udata, UDATA_TYPE_EBTABLES_POLICY, 1)) - return -1; + goto err_free_rule; nftnl_rule_set_data(r, NFTNL_RULE_USERDATA, nftnl_udata_buf_data(udata), nftnl_udata_buf_len(udata)); nftnl_udata_buf_free(udata); - if (!batch_rule_add(h, NFT_COMPAT_RULE_APPEND, r)) { - nftnl_rule_free(r); - return -1; - } + if (!batch_rule_add(h, NFT_COMPAT_RULE_APPEND, r)) + goto err_free_rule; + + /* add the rule to chain so it is freed later */ + nftnl_chain_rule_add_tail(r, c); return 0; +err_free_rule: + nftnl_rule_free(r); + return -1; } int ebt_set_user_chain_policy(struct nft_handle *h, const char *table, |