From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org, kuba@kernel.org,
pabeni@redhat.com, edumazet@kernel.org, horms@kernel.org,
fw@strlen.de, ja@ssi.bg
Subject: [PATCH net 02/10] netfilter: nft_payload: restrict checksum offsets to known values
Date: Mon, 19 Oct 2026 17:02:41 +0200 [thread overview]
Message-ID: <20261019150249.1879516-3-pablo@netfilter.org> (raw)
In-Reply-To: <20261019150249.1879516-1-pablo@netfilter.org>
From: Florian Westphal <fw@strlen.de>
We need to prevent userspace from corrupting e.g. tcp->doff, because
many locations in conntrack and conntrack helpers rely on
nf_conntrack_in() having validated the packet headers.
nft_payload allows to alter headers later which invalidates this
assumption.
The 'Fixes' commit restricts writes to safe fields, but there is
another side channel: the checksum location.
Restrict this too. Reported via sashiko/gemini.
Fixes: 112e447d17f7 ("netfilter: validate L4 headers after userspace packet writes")
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nft_payload.c | 40 ++++++++++++++++++++++++++++++-------
1 file changed, 33 insertions(+), 7 deletions(-)
diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
index e315d35f73d4..5b76af68b704 100644
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -20,6 +20,7 @@
#include <linux/tcp.h>
#include <linux/udp.h>
#include <net/gre.h>
+#include <linux/icmp.h>
#include <linux/icmpv6.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
@@ -1008,11 +1009,14 @@ 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 icmphdr, checksum) ||
+ 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 +1050,27 @@ 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);
+ case IPPROTO_ICMP:
+ return priv->csum_offset == offsetof(struct icmphdr, checksum);
+ }
+
+ return false;
+}
+
static bool nft_payload_csum_write_ok(const struct nft_pktinfo *pkt,
const struct nft_payload_set *priv)
{
@@ -1055,9 +1080,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:
--
2.47.3
next prev parent reply other threads:[~2026-10-19 15:03 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-19 15:02 [PATCH net 00/10] Netfilter/IPVS fixes for net Pablo Neira Ayuso
2026-10-19 15:02 ` [PATCH net 01/10] netfilter: nf_conntrack: avoid truncating IPv6 nexthdr offset Pablo Neira Ayuso
2026-10-19 15:55 ` netdev-bot+sinfo
2026-10-19 15:02 ` Pablo Neira Ayuso [this message]
2026-10-19 15:02 ` [PATCH net 03/10] ipvs: fix more races around the overload flag Pablo Neira Ayuso
2026-10-19 15:02 ` [PATCH net 04/10] ipvs: skip committing sync_threshold when proc_dointvec fails Pablo Neira Ayuso
2026-10-19 15:02 ` [PATCH net 05/10] netfilter: flowtable: use the vlan id, not the full tci, in the tuple key Pablo Neira Ayuso
2026-10-19 15:02 ` [PATCH net 06/10] netfilter: nf_reject: initialize IPCB at inet ingress Pablo Neira Ayuso
2026-10-19 15:02 ` [PATCH net 07/10] netfilter: nft_set_rbtree: narrow down range completion to anonymous sets Pablo Neira Ayuso
2026-10-19 15:02 ` [PATCH net 08/10] netfilter: xt_dccp: handle reserved options as single-byte Pablo Neira Ayuso
2026-10-19 15:02 ` [PATCH net 09/10] netfilter: flowtable: reset transport header after nf_flow_encap_pop() Pablo Neira Ayuso
2026-10-19 15:02 ` [PATCH net 10/10] netfilter: nf_conntrack_netlink: fix inverted IPv6 tuple filter 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=20261019150249.1879516-3-pablo@netfilter.org \
--to=pablo@netfilter.org \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=fw@strlen.de \
--cc=horms@kernel.org \
--cc=ja@ssi.bg \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pabeni@redhat.com \
/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