Linux Netfilter development
 help / color / mirror / Atom feed
From: Florian Westphal <fw@strlen.de>
To: Pablo Neira Ayuso <pablo@netfilter.org>
Cc: netfilter-devel@vger.kernel.org
Subject: Re: [PATCH nf-next 5/6] netfilter: nf_conntrack_helper: add refcounting from datapath
Date: Tue, 26 May 2026 19:54:51 +0200	[thread overview]
Message-ID: <ahXea1N1w40Siqin@strlen.de> (raw)
In-Reply-To: <20260526164049.148218-6-pablo@netfilter.org>

Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> There is already a refcount for control plane, to ensure the helper
> does not go away if it is used by rulesets.
> 
> This patch adds a new ->ct_refcnt field to struct nf_conntrack_helper
> which is bumped when the helper is used by the ct helper extension. Drop
> this reference count when the conntrack entry is released. This is a
> packet path refcount which ensures that struct nf_conntrack_helper
> remains in place for tricky scenarios where a packet sits in nfqueue, or
> elsewhere, with a conntrack that refers to this helper.
> 
> On helper removal, the help callback is set to NULL to disable it from
> packet path and, after rcu grace period, existing expectations are
> removed. Update ctnetlink to disable access to .to_nlattr and
> .from_nlattr if the helper is going away.
> 
> Remove nf_queue_nf_hook_drop() since it has proven not to be effective
> because packets with unconfirmed conntracks which are still flying to
> sit in nfqueue.
> 
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---
>  include/net/netfilter/nf_conntrack_helper.h | 25 +++++++++++++++---
>  net/netfilter/nf_conntrack_core.c           |  3 ++-
>  net/netfilter/nf_conntrack_helper.c         | 28 ++++++---------------
>  net/netfilter/nf_conntrack_netlink.c        | 12 ++++++---
>  net/netfilter/nf_conntrack_ovs.c            | 14 ++++++++++-
>  net/netfilter/nf_conntrack_proto.c          | 15 +++++++----
>  net/netfilter/nft_ct.c                      |  2 +-
>  net/netfilter/xt_CT.c                       |  7 +++---
>  8 files changed, 66 insertions(+), 40 deletions(-)
> 
> diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
> index 1956bc12bf56..a03cb4e59ea9 100644
> --- a/include/net/netfilter/nf_conntrack_helper.h
> +++ b/include/net/netfilter/nf_conntrack_helper.h
> @@ -35,20 +35,23 @@ enum nf_ct_helper_flags {
>  struct nf_conntrack_helper {
>  	struct hlist_node hnode;	/* Internal use. */
>  
> +	struct rcu_head rcu;
> +
>  	char name[NF_CT_HELPER_NAME_LEN]; /* name of the module */
>  	refcount_t refcnt;
>  	struct module *me;		/* pointer to self */
>  	struct nf_conntrack_expect_policy expect_policy[NF_CT_MAX_EXPECT_CLASSES];
>  
> +	refcount_t ct_refcnt;

Why do we need two reference counts?  I find this very confusing.
Which refcount frees the structure?  And can one refcount hit 0 while
other one is still in use?

>  	/* Function to call when data passes; return verdict, or -1 to
>             invalidate. */
> -	int (*help)(struct sk_buff *skb,
> -		    unsigned int protoff,
> -		    struct nf_conn *ct,
> -		    enum ip_conntrack_info conntrackinfo);
> +	int __rcu (*help)(struct sk_buff *skb, unsigned int protoff,
> +			  struct nf_conn *ct,
> +			  enum ip_conntrack_info conntrackinfo);
>  
>  	void (*destroy)(struct nf_conn *ct);

Why is help RCU protected while other callbacks are not?

'destroy' not being rcu protected implies that the helper module must
remain in memory until after kfree_rcu has released the underlying
storage anyway.

If thats true, why do we need rcu head and kfree_rcu in the first place?
module has to remain in memory until after last possible caller has
called me->destroy(), no?  If that is correct, then there is no need for
dynamically allocated storage.

> @@ -445,19 +432,18 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
>  	nf_ct_helper_count--;
>  	mutex_unlock(&nf_ct_helper_mutex);
>  
> +	/* This helper is going away, disable it. */
> +	rcu_assign_pointer(me->help, NULL);
> +

OK, so this signals pending removal (refcnt can still be elevated) to
prevent new packets/expectations from grabbing another reference.
Correct?  Is this a 'dying' flag or is there more to it?

I looked at patched 'nf_conntrack_ftp_fini', but I don't see anything
that spins/waits for completion of referencing entries.

How does ->destroy/to_nlattr/from_nlattr etc. work?

I expected to find something that does a busywait until refcount has
hit 0 to avoid any calls to the removed module.

The existing conntracks still hold a pointer to struct
nf_conntrack_helper, and its refcount can be elevated too, while
function pointers (not help, but others) are stale.

I suspect you need to move the function pointers to an 'op' sub-struct,
so that it can be cleared via single rcu_assign_pointer(me->help_ops, NULL) ?

But that still has one problem: if helper module is gone, how can you
call the destructor?

Maybe we need to accelerate pptp removal so the only user of destroy
is removed?

  reply	other threads:[~2026-05-26 17:55 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-26 16:40 [PATCH nf-next 0/6] add refcount to ct timeout/helper Pablo Neira Ayuso
2026-05-26 16:40 ` [PATCH nf-next 1/6] netfilter: nfnetlink_cthelper: use {READ,WRITE}_ONCE for accessing helper flags Pablo Neira Ayuso
2026-05-26 16:40 ` [PATCH nf-next 2/6] netfilter: cttimeout: detach dataplane timeout policy and add refcount Pablo Neira Ayuso
2026-05-26 16:40 ` [PATCH nf-next 3/6] netfilter: nf_conntrack_helper: dynamically allocate struct nf_conntrack_helper Pablo Neira Ayuso
2026-05-26 16:40 ` [PATCH nf-next 4/6] netfilter: nf_conntrack_pptp: move GRE specific cleanup to GRE tracker Pablo Neira Ayuso
2026-05-26 16:40 ` [PATCH nf-next 5/6] netfilter: nf_conntrack_helper: add refcounting from datapath Pablo Neira Ayuso
2026-05-26 17:54   ` Florian Westphal [this message]
2026-05-26 22:19     ` Pablo Neira Ayuso
2026-05-27 13:39       ` Florian Westphal
2026-05-26 16:40 ` [PATCH nf-next 6/6] netfilter: conntrack: revert ct extension genid infrastructure 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=ahXea1N1w40Siqin@strlen.de \
    --to=fw@strlen.de \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pablo@netfilter.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