]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
netfilter: allow exp not to be removed in nf_ct_find_expectation
authorXin Long <lucien.xin@gmail.com>
Sun, 16 Jul 2023 21:09:17 +0000 (17:09 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 7 Mar 2025 15:56:41 +0000 (16:56 +0100)
commit 4914109a8e1e494c6aa9852f9e84ec77a5fc643f upstream.

Currently nf_conntrack_in() calling nf_ct_find_expectation() will
remove the exp from the hash table. However, in some scenario, we
expect the exp not to be removed when the created ct will not be
confirmed, like in OVS and TC conntrack in the following patches.

This patch allows exp not to be removed by setting IPS_CONFIRMED
in the status of the tmpl.

Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Aaron Conole <aconole@redhat.com>
Acked-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/net/netfilter/nf_conntrack_expect.h
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_expect.c
net/netfilter/nft_ct.c

index 0855b60fba17583f44e5b225142595ffa579b89f..f642a87ea330a1ffe443229d26ed49b9b1b6abfd 100644 (file)
@@ -100,7 +100,7 @@ nf_ct_expect_find_get(struct net *net,
 struct nf_conntrack_expect *
 nf_ct_find_expectation(struct net *net,
                       const struct nf_conntrack_zone *zone,
-                      const struct nf_conntrack_tuple *tuple);
+                      const struct nf_conntrack_tuple *tuple, bool unlink);
 
 void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
                                u32 portid, int report);
index b7b2ed05ac5039fcd57b471005603b123d873877..ec4c39641089b26c4ff4482e38668e1afba31225 100644 (file)
@@ -1770,7 +1770,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
        cnet = nf_ct_pernet(net);
        if (cnet->expect_count) {
                spin_lock_bh(&nf_conntrack_expect_lock);
-               exp = nf_ct_find_expectation(net, zone, tuple);
+               exp = nf_ct_find_expectation(net, zone, tuple, !tmpl || nf_ct_is_confirmed(tmpl));
                if (exp) {
                        pr_debug("expectation arrives ct=%p exp=%p\n",
                                 ct, exp);
index 96948e98ec53ddaf8e364e3365204fa3301853e9..81ca348915c98c95200c0b4ae69d4a081978058c 100644 (file)
@@ -171,7 +171,7 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
 struct nf_conntrack_expect *
 nf_ct_find_expectation(struct net *net,
                       const struct nf_conntrack_zone *zone,
-                      const struct nf_conntrack_tuple *tuple)
+                      const struct nf_conntrack_tuple *tuple, bool unlink)
 {
        struct nf_conntrack_net *cnet = nf_ct_pernet(net);
        struct nf_conntrack_expect *i, *exp = NULL;
@@ -211,7 +211,7 @@ nf_ct_find_expectation(struct net *net,
                     !refcount_inc_not_zero(&exp->master->ct_general.use)))
                return NULL;
 
-       if (exp->flags & NF_CT_EXPECT_PERMANENT) {
+       if (exp->flags & NF_CT_EXPECT_PERMANENT || !unlink) {
                refcount_inc(&exp->use);
                return exp;
        } else if (del_timer(&exp->timeout)) {
index 2bfe3cdfbd581922dc2d61b03b8320a0f967006c..6157f8b4a3cea85817327c03803d587dd34071ba 100644 (file)
@@ -272,6 +272,7 @@ static void nft_ct_set_zone_eval(const struct nft_expr *expr,
                        regs->verdict.code = NF_DROP;
                        return;
                }
+               __set_bit(IPS_CONFIRMED_BIT, &ct->status);
        }
 
        nf_ct_set(skb, ct, IP_CT_NEW);
@@ -378,6 +379,7 @@ static bool nft_ct_tmpl_alloc_pcpu(void)
                        return false;
                }
 
+               __set_bit(IPS_CONFIRMED_BIT, &tmp->status);
                per_cpu(nft_ct_pcpu_template, cpu) = tmp;
        }