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@xxxxxx> --- iptables/nft.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/iptables/nft.c b/iptables/nft.c index addde1b53f37e..c0b5e2fc524a7 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, -- 2.25.1