Linux Netfilter development
 help / color / mirror / Atom feed
From: Florian Westphal <fw@strlen.de>
To: Zihan Xi <zihanx@nebusec.ai>
Cc: netfilter-devel@vger.kernel.org, pablo@netfilter.org,
	phil@nwl.cc, davem@davemloft.net, edumazet@google.com,
	pabeni@redhat.com, horms@kernel.org, avagin@gmail.com,
	vega@nebusec.ai
Subject: Re: [PATCH nf v2 2/2] netfilter: nf_conntrack_tcp: defer tcp_in_window invalid logging until after unlock
Date: Thu, 30 Jul 2026 22:28:23 +0200	[thread overview]
Message-ID: <amuz5x-ib-Cuatcn@strlen.de> (raw)
In-Reply-To: <27612fbff3730c5d63a0e3fb0f51aeeed77ed5d7.1785348197.git.zihanx@nebusec.ai>

Zihan Xi <zihanx@nebusec.ai> wrote:
> tcp_in_window() can emit several invalid-packet logs while ct->lock is
> still held.  If invalid logging is routed to nfnetlink_log with
> conntrack export enabled, this can re-enter conntrack netlink glue and
> recurse into tcp_to_nlattr() on the same conntrack.
> 
> Fix this by storing only the minimal invalid-log context for the
> remaining tcp_in_window() cases and emitting the actual log after
> releasing ct->lock.  Rename the helper to reflect that it now records
> context instead of logging immediately, and add an explicit lockdep
> assertion plus comment to document that invalid TCP logs must not be
> emitted while ct->lock is held.
> 
> Fixes: d48668052b26 ("netfilter: fix nf_l4proto_log_invalid to log invalid packets")
> Cc: stable@vger.kernel.org
> Reported-by: Vega <vega@nebusec.ai>
> Assisted-by: Codex:gpt-5.4
> Signed-off-by: Zihan Xi <zihanx@nebusec.ai>
> ---
> changes in v2:
>   - Keep only the tcp_in_window() invalid logging cases in this patch.
>   - Rename the helper to reflect that it stores invalid-log context.
>   - Add a lockdep assertion and comment documenting that invalid logs must not be emitted under ct->lock.
>   - v1 Link: https://lore.kernel.org/all/cover.1785307980.git.zihanx@nebusec.ai/
> ---
>  net/netfilter/nf_conntrack_proto_tcp.c | 113 ++++++++++++++++++-------
>  1 file changed, 82 insertions(+), 31 deletions(-)
> 
> diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
> index ef31dcaffd19..e5875b7528fe 100644
> --- a/net/netfilter/nf_conntrack_proto_tcp.c
> +++ b/net/netfilter/nf_conntrack_proto_tcp.c
> @@ -480,37 +480,87 @@ static void tcp_init_sender(struct ip_ct_tcp_state *sender,
>  	}
>  }
>  
> -__printf(6, 7)
> -static enum nf_ct_tcp_action nf_tcp_log_invalid(const struct sk_buff *skb,
> -						const struct nf_conn *ct,
> -						const struct nf_hook_state *state,
> -						const struct ip_ct_tcp_state *sender,
> -						enum nf_ct_tcp_action ret,
> -						const char *fmt, ...)
> +enum nf_tcp_invalid_log_type {
> +	NF_TCP_LOG_NONE,
> +	NF_TCP_LOG_OVERSHOT,
> +	NF_TCP_LOG_SEQ_OVER,
> +	NF_TCP_LOG_ACK_OVER,
> +	NF_TCP_LOG_SEQ_UNDER,
> +	NF_TCP_LOG_ACK_UNDER,
> +};
> +
> +struct nf_tcp_invalid_log {
> +	enum nf_tcp_invalid_log_type type;
> +	u32 value;
> +};
> +
> +static enum nf_ct_tcp_action
> +nf_tcp_store_invalid(const struct nf_conn *ct,
> +		     const struct ip_ct_tcp_state *sender,
> +		     struct nf_tcp_invalid_log *log,
> +		     enum nf_ct_tcp_action ret,
> +		     enum nf_tcp_invalid_log_type type,
> +		     u32 value)
>  {
>  	const struct nf_tcp_net *tn = nf_tcp_pernet(nf_ct_net(ct));
> -	struct va_format vaf;
> -	va_list args;
>  	bool be_liberal;
>  
>  	be_liberal = sender->flags & IP_CT_TCP_FLAG_BE_LIBERAL || tn->tcp_be_liberal;
>  	if (be_liberal)
>  		return NFCT_TCP_ACCEPT;
>  
> -	va_start(args, fmt);
> -	vaf.fmt = fmt;
> -	vaf.va = &args;
> -	nf_ct_l4proto_log_invalid(skb, ct, state, "%pV", &vaf);
> -	va_end(args);
> -
> +	log->type = type;
> +	log->value = value;
>  	return ret;
>  }
>  
> +static void nf_tcp_log_invalid(const struct sk_buff *skb,
> +			       const struct nf_conn *ct,
> +			       const struct nf_hook_state *state,
> +			       const struct nf_tcp_invalid_log *log)
> +{
> +	/* nfnetlink_log may re-enter conntrack attribute dumping and try to
> +	 * take ct->lock again via tcp_to_nlattr(), so invalid TCP logs must
> +	 * only be emitted after dropping ct->lock.
> +	 */
> +	lockdep_assert_not_held(&ct->lock);
> +
> +	switch (log->type) {
> +	case NF_TCP_LOG_OVERSHOT:
> +		nf_ct_l4proto_log_invalid(skb, ct, state,
> +					  "%u bytes more than expected",
> +					  log->value);

Can you move the comment and the lockdep assert into
nf_ct_l4proto_log_invalid() so we can catch offenders outside
tcp as well?

SCTP seems to be buggy as well.

Other than that:

Reviewed-by: Florian Westphal <fw@strlen.de>

You can keep this tag in next iteration.

  reply	other threads:[~2026-07-30 20:28 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-30 13:55 [PATCH nf v2 0/2] netfilter: fix TCP conntrack invalid-log deadlock Zihan Xi
2026-07-30 13:55 ` [PATCH nf v2 1/2] netfilter: nf_conntrack_tcp: defer timeout-lowering invalid log until after unlock Zihan Xi
2026-07-30 20:25   ` Florian Westphal
2026-07-31 10:26   ` Pablo Neira Ayuso
2026-07-30 13:55 ` [PATCH nf v2 2/2] netfilter: nf_conntrack_tcp: defer tcp_in_window invalid logging " Zihan Xi
2026-07-30 20:28   ` Florian Westphal [this message]
2026-07-31 10:18     ` 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=amuz5x-ib-Cuatcn@strlen.de \
    --to=fw@strlen.de \
    --cc=avagin@gmail.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=pablo@netfilter.org \
    --cc=phil@nwl.cc \
    --cc=vega@nebusec.ai \
    --cc=zihanx@nebusec.ai \
    /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