[PATCH] net: gue: reject invalid REMCSUM offsets

From: Jérémy Jean

Date: Thu Aug 20 2026 - 18:03:25 EST


The REMCSUM option carries an absolute checksum start and checksum field
offset. gue_remcsum() passes them to skb_remcsum_process(), whose
partial path stores offset - start in the u16 skb->csum_offset. If
offset is less than start, this underflows (for example, 1/0 becomes
0xffff).

A forwarded packet can retain CHECKSUM_PARTIAL and reach a
NETIF_F_HW_CSUM driver which trusts the metadata, leading
skb_copy_and_csum_dev() to write two bytes about 64 KiB beyond the
destination buffer.

Reject reversed tuples in both normal and GRO receive paths.

Fixes: fe881ef11cf0 ("gue: Use checksum partial with remote checksum offload")
Assisted-by: Codex:gpt-5
Signed-off-by: Jérémy Jean <Jeremy.Jean@xxxxxxxxxxxxxxxxx>
---
net/ipv4/fou_core.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/net/ipv4/fou_core.c b/net/ipv4/fou_core.c
index ab09dfcdecbd..c4b8b7293994 100644
--- a/net/ipv4/fou_core.c
+++ b/net/ipv4/fou_core.c
@@ -97,6 +97,9 @@ static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr,
size_t plen = sizeof(struct udphdr) + hdrlen +
max_t(size_t, offset + sizeof(u16), start);

+ if (unlikely(offset < start))
+ return NULL;
+
if (skb->remcsum_offload)
return guehdr;

@@ -308,6 +311,9 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
size_t start = ntohs(pd[0]);
size_t offset = ntohs(pd[1]);

+ if (unlikely(offset < start))
+ return NULL;
+
if (skb->remcsum_offload)
return guehdr;

--
2.47.3