Netdev List
 help / color / mirror / Atom feed
From: Jakub Kicinski <kuba@kernel.org>
To: pablo@netfilter.org
Cc: Jakub Kicinski <kuba@kernel.org>,
	netfilter-devel@vger.kernel.org, davem@davemloft.net,
	netdev@vger.kernel.org, pabeni@redhat.com, edumazet@google.com,
	horms@kernel.org, fw@strlen.de, ja@ssi.bg
Subject: Re: [PATCH net 07/12] netfilter: nft_payload: restrict checksum offsets to known values
Date: Thu,  3 Sep 2026 19:01:48 -0700	[thread overview]
Message-ID: <20260904020148.3549914-1-kuba@kernel.org> (raw)
In-Reply-To: <20260903004149.1037028-8-pablo@netfilter.org>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
netfilter: nft_payload: restrict checksum offsets to known values

This restricts the NFT_PAYLOAD_CSUM_INET checksum offset for transport
header writes, both at rule load time in
nft_payload_validate_inet_csum_offset() and at packet time via the new
nft_payload_csum_th_write_ok() helper.  Previously the transport header
case accepted any csum_offset.

> diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
> index e315d35f73d4..70f70a65e327 100644
> --- a/net/netfilter/nft_payload.c
> +++ b/net/netfilter/nft_payload.c
> @@ -1008,11 +1008,13 @@ static bool nft_payload_validate_inet_csum_offset(const struct nft_ctx *ctx,
>  		if (priv->csum_flags) /* makes no sense, asks for "re-update" of L4 checksum */
>  			return false;
>  
> -		/* no further check here; offset can't be negative so bogus
> -		 * offsets can corrupt L4 or payload but not l3 headers.
> -		 * We already allow arbitrary l4/inner payload writes.
> -		 */
> -		return true;
> +		/* Validate csum_offset is one of the supported transport header checksums */
> +		if (priv->csum_offset == offsetof(struct tcphdr, check) ||
> +		    priv->csum_offset == offsetof(struct udphdr, check) ||
> +		    priv->csum_offset == offsetof(struct icmp6hdr, icmp6_cksum))
> +			return true;
> +
> +		return false;
>  	case NFT_PAYLOAD_INNER_HEADER:
>  		return true;
>  	case NFT_PAYLOAD_TUN_HEADER:
> @@ -1046,6 +1048,25 @@ static bool nft_payload_csum_nh_write_ok(const struct nft_payload_set *priv,
>  	return false;
>  }
>  
> +static bool nft_payload_csum_th_write_ok(const struct nft_payload_set *priv,
> +					 const struct nft_pktinfo *pkt)
> +{
> +	if (!(pkt->flags & NFT_PKTINFO_L4PROTO))
> +		return false;
> +
> +	switch (pkt->tprot) {
> +	case IPPROTO_TCP:
> +		return priv->csum_offset == offsetof(struct tcphdr, check);
> +	case IPPROTO_UDP:
> +	case IPPROTO_UDPLITE:
> +		return priv->csum_offset == offsetof(struct udphdr, check);
> +	case IPPROTO_ICMPV6:
> +		return priv->csum_offset == offsetof(struct icmp6hdr, icmp6_cksum);
> +	}
> +
> +	return false;
> +}

[Severity: High]
Should nft_payload_csum_th_write_ok() also handle IPPROTO_ICMP?  There is
no arm for it, and neither IPPROTO_ICMP nor struct icmphdr appear anywhere
in nft_payload.c (linux/icmp.h is not included), so pkt->tprot ==
IPPROTO_ICMP falls out of the switch and returns false.

At the same time the load time check above accepts csum_offset == 2,
because the two checksum fields sit at the same offset:

include/uapi/linux/icmp.h:
struct icmphdr {
  __u8		type;
  __u8		code;
  __sum16	checksum;
  ...

So a rule such as:

    nft add rule ip filter output icmp id set 1

still loads without error, but at packet time the checksum fixup is
skipped.  In nft_payload_set_eval() the helper is only the middle operand
of an && chain, so a false return does not reach the err label:

	if (priv->csum_type == NFT_PAYLOAD_CSUM_INET &&
	    nft_payload_csum_write_ok(pkt, priv) &&
	    nft_payload_csum_inet(skb, src, fsum, tsum, csum_offset))
		goto err;
	...
	if (skb_ensure_writable(skb, max(offset + priv->len, 0)) ||
	    skb_store_bits(skb, offset, src, priv->len) < 0)
		goto err;

Does this mean the ICMPv4 header bytes are still rewritten by
skb_store_bits() while the old checksum is left in place, so such packets
go out with a stale checksum?  Before this patch the
NFT_PAYLOAD_TRANSPORT_HEADER case of nft_payload_csum_write_ok() returned
true unconditionally, so previously working ICMPv4 mangling rules would
change behaviour here.

The accepted protocol list looks like the one in
nft_payload_l4csum_offset(), which serves the csum_flags pseudo-header
path and therefore has a reason to omit ICMPv4.  Is that the right list to
reuse for the NFT_PAYLOAD_CSUM_INET path?

Two things that may be worth considering: adding

	case IPPROTO_ICMP:
		return priv->csum_offset == offsetof(struct icmphdr, checksum);

to nft_payload_csum_th_write_ok(), and making the run time refusal set
NFT_BREAK rather than silently skipping the checksum update, so load time
and run time agree.

> @@ -1055,9 +1076,10 @@ static bool nft_payload_csum_write_ok(const struct nft_pktinfo *pkt,
>  	case NFT_PAYLOAD_NETWORK_HEADER:
>  		return nft_payload_csum_nh_write_ok(priv, pkt);
>  	case NFT_PAYLOAD_TRANSPORT_HEADER:
> +		return nft_payload_csum_th_write_ok(priv, pkt);
>  	case NFT_PAYLOAD_INNER_HEADER:
> -		/* neither offsets are validated, offsets cannot be
> -		 * negative so real l3 headers cannot be mangled.
> +		/* offset is not validated, offset cannot be
> +		 * negative so real l3/l4 headers cannot be mangled.
>  		 */
>  		return true;
>  	case NFT_PAYLOAD_TUN_HEADER:

[ ... ]

  reply	other threads:[~2026-09-04  2:01 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-03  0:41 [PATCH net 00/12] Netfilter/IPVS fixes for net Pablo Neira Ayuso
2026-09-03  0:41 ` [PATCH net 01/12] ipvs: reject invalid states in connection template sync records Pablo Neira Ayuso
2026-09-03  0:41 ` [PATCH net 02/12] ipvs: fix reversed sequence option serialization Pablo Neira Ayuso
2026-09-03  0:41 ` [PATCH net 03/12] netfilter: nf_conntrack_sip: fix OOB read in sip_skip_whitespace() Pablo Neira Ayuso
2026-09-03  0:41 ` [PATCH net 04/12] netfilter: cttimeout: prevent UAF during module unload Pablo Neira Ayuso
2026-09-03  0:41 ` [PATCH net 05/12] netfilter: nf_log: unregister loggers before per-net teardown Pablo Neira Ayuso
2026-09-03  0:41 ` [PATCH net 06/12] ipvs: bound LBLCR and LBLC cache growth Pablo Neira Ayuso
2026-09-04  2:01   ` Jakub Kicinski
2026-09-04  4:20     ` Julian Anastasov
2026-09-03  0:41 ` [PATCH net 07/12] netfilter: nft_payload: restrict checksum offsets to known values Pablo Neira Ayuso
2026-09-04  2:01   ` Jakub Kicinski [this message]
2026-09-04  5:56     ` Florian Westphal
2026-09-03  0:41 ` [PATCH net 08/12] netfilter: nfnetlink_log: cope with concurrent instance destruction Pablo Neira Ayuso
2026-09-03  0:41 ` [PATCH net 09/12] netfilter: nfnetlink_queue: hold nfnl mutex in event notifier Pablo Neira Ayuso
2026-09-04  2:01   ` Jakub Kicinski
2026-09-04  5:56     ` Florian Westphal
2026-09-03  0:41 ` [PATCH net 10/12] netfilter: arp_tables: remove the 32bit compat interface Pablo Neira Ayuso
2026-09-03  0:41 ` [PATCH net 11/12] netfilter: ip6_tables: set F_PROTO when proto value is nonzero Pablo Neira Ayuso
2026-09-03  0:41 ` [PATCH net 12/12] netfilter: report NLM_F_DUMP_FILTERED when all is filtered out Pablo Neira Ayuso
2026-09-04  2:04 ` [PATCH net 00/12] Netfilter/IPVS fixes for net Jakub Kicinski
2026-09-04  5:57   ` Florian Westphal
2026-09-04 10:55     ` Pablo Neira Ayuso
2026-09-04 10:59       ` Florian Westphal

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=20260904020148.3549914-1-kuba@kernel.org \
    --to=kuba@kernel.org \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=fw@strlen.de \
    --cc=horms@kernel.org \
    --cc=ja@ssi.bg \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --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