[SRU][F][PATCH 1/1] netfilter: allow exp not to be removed in nf_ct_find_expectation
Tim Whisonant
tim.whisonant at canonical.com
Fri Mar 28 17:33:18 UTC 2025
From: Xin Long <lucien.xin at gmail.com>
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 at gmail.com>
Acked-by: Aaron Conole <aconole at redhat.com>
Acked-by: Florian Westphal <fw at strlen.de>
Signed-off-by: Paolo Abeni <pabeni at redhat.com>
(backported from commit 4914109a8e1e494c6aa9852f9e84ec77a5fc643f)
[tswhison: adjusted context due to missing commits
b0a7ab4a7765 ("netfilter: conntrack: un-inline nf_ct_ecache_ext_add")
90d1daa45849 ("netfilter: conntrack: add nf_conntrack_events autodetect mode")
0418b989a467 ("netfilter: nftables: add nf_ct_pernet() helper function")
719774377622 ("netfilter: conntrack: convert to refcount_t api")]
CVE-2023-52927
Signed-off-by: Tim Whisonant <tim.whisonant at canonical.com>
---
include/net/netfilter/nf_conntrack_expect.h | 2 +-
net/netfilter/nf_conntrack_core.c | 2 +-
net/netfilter/nf_conntrack_expect.c | 4 ++--
net/netfilter/nft_ct.c | 2 ++
4 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 0855b60fba175..f642a87ea330a 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -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);
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index fb1f12bb0ff2c..d47c76cd011c3 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1455,7 +1455,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
local_bh_disable();
if (net->ct.expect_count) {
spin_lock(&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);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 42557d2b6a908..45f29e28aba3f 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -156,7 +156,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_expect *i, *exp = NULL;
unsigned int h;
@@ -195,7 +195,7 @@ nf_ct_find_expectation(struct net *net,
!atomic_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)) {
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index 0c7f091d7d54d..242129e42e039 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -267,6 +267,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);
}
atomic_inc(&ct->ct_general.use);
@@ -375,6 +376,7 @@ static bool nft_ct_tmpl_alloc_pcpu(void)
}
atomic_set(&tmp->ct_general.use, 1);
+ __set_bit(IPS_CONFIRMED_BIT, &tmp->status);
per_cpu(nft_ct_pcpu_template, cpu) = tmp;
}
--
2.43.0
More information about the kernel-team
mailing list