From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: fw@strlen.de
Subject: [PATCH nf,v2] netfilter: conntrack: add dead flag to helpers
Date: Thu, 14 May 2026 16:30:16 +0200 [thread overview]
Message-ID: <20260514143016.874811-1-pablo@netfilter.org> (raw)
Add a new NF_CT_HELPER_F_DEAD helper flag to notify the packet path that
this helper is going away. Thus, helpers are effectively disabled and no
new expectations are created while removing the expectations created by
this helper as well as unhelping the existing conntrack entries.
Add the check for NF_CT_HELPER_F_DEAD in the packet path to:
- Conntrack confirmation path which invokes the helper callback.
- Propagation of helper to conntrack via expectation.
- OVS ct helper invocation.
Fixes: 12f7a505331e ("netfilter: add user-space connection tracking helper infrastructure")
Reported-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: use READ_ONCE() and WRITE_ONCE() to modify helper flags are AI reporter suggests.
include/net/netfilter/nf_conntrack_helper.h | 8 ++++++++
net/netfilter/nf_conntrack_core.c | 2 +-
net/netfilter/nf_conntrack_helper.c | 5 ++++-
net/netfilter/nf_conntrack_ovs.c | 3 +++
net/netfilter/nf_conntrack_proto.c | 2 +-
5 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index de2f956abf34..b6ff7dc65c97 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -25,6 +25,7 @@ struct module;
enum nf_ct_helper_flags {
NF_CT_HELPER_F_USERSPACE = (1 << 0),
NF_CT_HELPER_F_CONFIGURED = (1 << 1),
+ NF_CT_HELPER_F_DEAD = (1 << 2),
};
#define NF_CT_HELPER_NAME_LEN 16
@@ -63,6 +64,13 @@ struct nf_conntrack_helper {
char nat_mod_name[NF_CT_HELPER_NAME_LEN];
};
+static inline bool nf_ct_helper_alive(const struct nf_conntrack_helper *helper)
+{
+ unsigned int helper_flags = READ_ONCE(helper->flags);
+
+ return likely(!(helper_flags & NF_CT_HELPER_F_DEAD));
+}
+
/* Must be kept in sync with the classes defined by helpers */
#define NF_CT_MAX_EXPECT_CLASSES 4
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 8ba5b22a1eef..d54da6babcfe 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1818,7 +1818,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
/* exp->master safe, refcnt bumped in nf_ct_find_expectation */
ct->master = exp->master;
assign_helper = rcu_dereference(exp->assign_helper);
- if (assign_helper) {
+ if (assign_helper && nf_ct_helper_alive(assign_helper)) {
help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
if (help)
rcu_assign_pointer(help->helper, assign_helper);
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index b594cd244fe1..9f4ba1b0b5ab 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -415,8 +415,11 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
nf_ct_helper_count--;
mutex_unlock(&nf_ct_helper_mutex);
+ WRITE_ONCE(me->flags, me->flags | NF_CT_HELPER_F_DEAD);
+
/* Make sure every nothing is still using the helper unless its a
- * connection in the hash.
+ * connection in the hash, no more expectations are created after
+ * this rcu grace period.
*/
synchronize_rcu();
diff --git a/net/netfilter/nf_conntrack_ovs.c b/net/netfilter/nf_conntrack_ovs.c
index a6988eeb1579..eeeb85c18a84 100644
--- a/net/netfilter/nf_conntrack_ovs.c
+++ b/net/netfilter/nf_conntrack_ovs.c
@@ -28,6 +28,9 @@ int nf_ct_helper(struct sk_buff *skb, struct nf_conn *ct,
if (!helper)
return NF_ACCEPT;
+ if (!nf_ct_helper_alive(helper))
+ return NF_ACCEPT;
+
if (helper->tuple.src.l3num != NFPROTO_UNSPEC &&
helper->tuple.src.l3num != proto)
return NF_ACCEPT;
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 50ddd3d613e1..b2ac5bd491cb 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -174,7 +174,7 @@ unsigned int nf_confirm(void *priv,
/* rcu_read_lock()ed by nf_hook */
helper = rcu_dereference(help->helper);
- if (helper) {
+ if (helper && nf_ct_helper_alive(helper)) {
ret = helper->help(skb,
protoff,
ct, ctinfo);
--
2.47.3
next reply other threads:[~2026-05-14 14:30 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-14 14:30 Pablo Neira Ayuso [this message]
2026-05-14 14:43 ` [PATCH nf,v2] netfilter: conntrack: add dead flag to helpers Florian Westphal
2026-05-14 15:10 ` Pablo Neira Ayuso
2026-05-14 15:44 ` Florian Westphal
2026-05-14 23:30 ` Pablo Neira Ayuso
2026-05-14 23:53 ` Pablo Neira Ayuso
2026-05-14 23:55 ` Florian Westphal
2026-05-15 0:10 ` Pablo Neira Ayuso
2026-05-15 0:21 ` Pablo Neira Ayuso
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=20260514143016.874811-1-pablo@netfilter.org \
--to=pablo@netfilter.org \
--cc=fw@strlen.de \
--cc=netfilter-devel@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.