]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netfilter: nf_conncount: fix leaked ct in error paths
authorFernando Fernandez Mancera <fmancera@suse.de>
Fri, 5 Dec 2025 11:58:01 +0000 (12:58 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Jan 2026 12:09:43 +0000 (13:09 +0100)
[ Upstream commit 2e2a720766886190a6d35c116794693aabd332b6 ]

There are some situations where ct might be leaked as error paths are
skipping the refcounted check and return immediately. In order to solve
it make sure that the check is always called.

Fixes: be102eb6a0e7 ("netfilter: nf_conncount: rework API to use sk_buff directly")
Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/netfilter/nf_conncount.c

index 97b631a81484d4d60cf3b7a46b47e22e8d7cc86e..c00b8e522c5a72478c31ad3b568547e3e06dae54 100644 (file)
@@ -172,14 +172,14 @@ static int __nf_conncount_add(struct net *net,
        struct nf_conn *found_ct;
        unsigned int collect = 0;
        bool refcounted = false;
+       int err = 0;
 
        if (!get_ct_or_tuple_from_skb(net, skb, l3num, &ct, &tuple, &zone, &refcounted))
                return -ENOENT;
 
        if (ct && nf_ct_is_confirmed(ct)) {
-               if (refcounted)
-                       nf_ct_put(ct);
-               return -EEXIST;
+               err = -EEXIST;
+               goto out_put;
        }
 
        if ((u32)jiffies == list->last_gc)
@@ -231,12 +231,16 @@ static int __nf_conncount_add(struct net *net,
        }
 
 add_new_node:
-       if (WARN_ON_ONCE(list->count > INT_MAX))
-               return -EOVERFLOW;
+       if (WARN_ON_ONCE(list->count > INT_MAX)) {
+               err = -EOVERFLOW;
+               goto out_put;
+       }
 
        conn = kmem_cache_alloc(conncount_conn_cachep, GFP_ATOMIC);
-       if (conn == NULL)
-               return -ENOMEM;
+       if (conn == NULL) {
+               err = -ENOMEM;
+               goto out_put;
+       }
 
        conn->tuple = tuple;
        conn->zone = *zone;
@@ -249,7 +253,7 @@ add_new_node:
 out_put:
        if (refcounted)
                nf_ct_put(ct);
-       return 0;
+       return err;
 }
 
 int nf_conncount_add_skb(struct net *net,
@@ -446,11 +450,10 @@ restart:
 
                rb_link_node_rcu(&rbconn->node, parent, rbnode);
                rb_insert_color(&rbconn->node, root);
-
-               if (refcounted)
-                       nf_ct_put(ct);
        }
 out_unlock:
+       if (refcounted)
+               nf_ct_put(ct);
        spin_unlock_bh(&nf_conncount_locks[hash]);
        return count;
 }