netfilter: nf_tables: Fix a memory leak in nf_tables_updchain
authorQuan Tian <tianquan23@gmail.com>
Wed, 6 Mar 2024 17:24:02 +0000 (01:24 +0800)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 21 Mar 2024 11:12:06 +0000 (12:12 +0100)
If nft_netdev_register_hooks() fails, the memory associated with
nft_stats is not freed, causing a memory leak.

This patch fixes it by moving nft_stats_alloc() down after
nft_netdev_register_hooks() succeeds.

Fixes: b9703ed44ffb ("netfilter: nf_tables: support for adding new devices to an existing netdev chain")
Signed-off-by: Quan Tian <tianquan23@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/netfilter/nf_tables_api.c

index 984c1c83ee38c70c708303593a2d471fdfb8a449..5fa3d3540c93c003737fb16ef1e6e7514580e97a 100644 (file)
@@ -2631,19 +2631,6 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
                }
        }
 
-       if (nla[NFTA_CHAIN_COUNTERS]) {
-               if (!nft_is_base_chain(chain)) {
-                       err = -EOPNOTSUPP;
-                       goto err_hooks;
-               }
-
-               stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
-               if (IS_ERR(stats)) {
-                       err = PTR_ERR(stats);
-                       goto err_hooks;
-               }
-       }
-
        if (!(table->flags & NFT_TABLE_F_DORMANT) &&
            nft_is_base_chain(chain) &&
            !list_empty(&hook.list)) {
@@ -2658,6 +2645,20 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
        }
 
        unregister = true;
+
+       if (nla[NFTA_CHAIN_COUNTERS]) {
+               if (!nft_is_base_chain(chain)) {
+                       err = -EOPNOTSUPP;
+                       goto err_hooks;
+               }
+
+               stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
+               if (IS_ERR(stats)) {
+                       err = PTR_ERR(stats);
+                       goto err_hooks;
+               }
+       }
+
        err = -ENOMEM;
        trans = nft_trans_alloc(ctx, NFT_MSG_NEWCHAIN,
                                sizeof(struct nft_trans_chain));