From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: Florian Westphal <fw@strlen.de>,
Pablo Neira Ayuso <pablo@netfilter.org>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 5.15.y 1/5] netfilter: cttimeout: decouple unlink and free on netns destruction
Date: Wed, 16 Sep 2026 21:33:09 -0400 [thread overview]
Message-ID: <20260917013313.3594807-1-sashal@kernel.org> (raw)
In-Reply-To: <2026091646-antonym-acid-ca2a@gregkh>
From: Florian Westphal <fw@strlen.de>
[ Upstream commit 78222bacfca97cb18505df1ba5f3591864498a7e ]
Make it so netns pre_exit unlinks the objects from the pernet list, so
they cannot be found anymore.
netns core issues a synchronize_rcu() before calling the exit hooks so
any the time the exit hooks run unconfirmed nf_conn entries have been
free'd or they have been committed to the hashtable.
The exit hook still tags unconfirmed entries as dying, this can
now be removed in a followup change.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Stable-dep-of: fec9b1de0d02 ("netfilter: cttimeout: prevent UAF during module unload")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/net/netfilter/nf_conntrack_timeout.h | 8 ------
net/netfilter/nfnetlink_cttimeout.c | 30 ++++++++++++++++++--
2 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_timeout.h b/include/net/netfilter/nf_conntrack_timeout.h
index 16e024ca15875..1fe6b634a6ff4 100644
--- a/include/net/netfilter/nf_conntrack_timeout.h
+++ b/include/net/netfilter/nf_conntrack_timeout.h
@@ -18,14 +18,6 @@ struct nf_ct_timeout {
char data[];
};
-struct ctnl_timeout {
- struct list_head head;
- struct rcu_head rcu_head;
- refcount_t refcnt;
- char name[CTNL_TIMEOUT_NAME_MAX];
- struct nf_ct_timeout timeout;
-};
-
struct nf_conn_timeout {
struct nf_ct_timeout __rcu *timeout;
};
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
index c57673d499be7..2a241ed20edd2 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -33,8 +33,19 @@
static unsigned int nfct_timeout_id __read_mostly;
+struct ctnl_timeout {
+ struct list_head head;
+ struct rcu_head rcu_head;
+ refcount_t refcnt;
+ char name[CTNL_TIMEOUT_NAME_MAX];
+ struct nf_ct_timeout timeout;
+
+ struct list_head free_head;
+};
+
struct nfct_timeout_pernet {
struct list_head nfct_timeout_list;
+ struct list_head nfct_timeout_freelist;
};
MODULE_LICENSE("GPL");
@@ -578,10 +589,24 @@ static int __net_init cttimeout_net_init(struct net *net)
struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
INIT_LIST_HEAD(&pernet->nfct_timeout_list);
+ INIT_LIST_HEAD(&pernet->nfct_timeout_freelist);
return 0;
}
+static void __net_exit cttimeout_net_pre_exit(struct net *net)
+{
+ struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
+ struct ctnl_timeout *cur, *tmp;
+
+ list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_list, head) {
+ list_del_rcu(&cur->head);
+ list_add(&cur->free_head, &pernet->nfct_timeout_freelist);
+ }
+
+ /* core calls synchronize_rcu() after this */
+}
+
static void __net_exit cttimeout_net_exit(struct net *net)
{
struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
@@ -590,8 +615,8 @@ static void __net_exit cttimeout_net_exit(struct net *net)
nf_ct_unconfirmed_destroy(net);
nf_ct_untimeout(net, NULL);
- list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_list, head) {
- list_del_rcu(&cur->head);
+ list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_freelist, head) {
+ list_del(&cur->free_head);
if (refcount_dec_and_test(&cur->refcnt))
kfree_rcu(cur, rcu_head);
@@ -600,6 +625,7 @@ static void __net_exit cttimeout_net_exit(struct net *net)
static struct pernet_operations cttimeout_ops = {
.init = cttimeout_net_init,
+ .pre_exit = cttimeout_net_pre_exit,
.exit = cttimeout_net_exit,
.id = &nfct_timeout_id,
.size = sizeof(struct nfct_timeout_pernet),
--
2.53.0
next prev parent reply other threads:[~2026-09-17 1:33 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-16 15:32 FAILED: patch "[PATCH] netfilter: cttimeout: prevent UAF during module unload" failed to apply to 5.15-stable tree gregkh
2026-09-17 1:33 ` Sasha Levin [this message]
2026-09-17 1:33 ` [PATCH 5.15.y 2/5] netfilter: remove nf_ct_unconfirmed_destroy helper Sasha Levin
2026-09-17 1:33 ` [PATCH 5.15.y 3/5] netfilter: cttimeout: fix slab-out-of-bounds read in cttimeout_net_exit Sasha Levin
2026-09-17 1:33 ` [PATCH 5.15.y 4/5] netfilter: cttimeout: detach dataplane timeout policy and repurpose refcount Sasha Levin
2026-09-17 1:33 ` [PATCH 5.15.y 5/5] netfilter: cttimeout: prevent UAF during module unload Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260917013313.3594807-1-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=fw@strlen.de \
--cc=pablo@netfilter.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox