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.
next prev parent 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