]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
nft: Fix leaks in ebt_add_policy_rule()
authorPhil Sutter <phil@nwl.cc>
Mon, 4 May 2020 17:30:29 +0000 (19:30 +0200)
committerPhil Sutter <phil@nwl.cc>
Mon, 11 May 2020 12:28:29 +0000 (14:28 +0200)
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>
iptables/nft.c

index addde1b53f37ef9d3e8f3f44626e29e473b8fd39..c0b5e2fc524a7a1a6aeb92a0706493accaf4196d 100644 (file)
@@ -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,