* [PATCH net v2] net: gro: avoid parsing headers from shared fragments
@ 2026-10-31 5:07 Kyle Zeng
0 siblings, 0 replies; only message in thread
From: Kyle Zeng @ 2026-10-31 5:07 UTC (permalink / raw)
To: netdev; +Cc: edumazet, davem, linux-kernel, outbounddisclosures
When an skb has an empty linear head, skb_gro_reset_offset() can expose
the first page fragment directly to GRO header parsers. For an
SKBFL_SHARED_FRAG skb, those bytes may still be writable through a file
mapping. Headers validated during receive can therefore differ from the
headers later copied into the linear head and used during completion.
For example, changing an IPv6 destination-options length between the
short and full header fetches in ipv6_gro_pull_exthdrs() can make
ipv6_gro_complete() pass an out-of-bounds offset to udp6_gro_complete().
A userspace reproducer triggered a KASAN slab-out-of-bounds read there
on an unmodified kernel as UID 1000. The same completion path can write
the UDP checksum and length through the invalid offset. The packet has
trusted TCP GSO metadata and spliced file data, so it reaches completion
without an skb zerocopy destructor or a second GRO packet.
Disable the direct-fragment fast path for skbs with externally writable
fragments. With an empty linear head, frag0_len remains zero, so
skb_gro_header_slow() pulls each required header into the linear head
before it is inspected. Subsequent pulls preserve the validated prefix.
This covers both gro_receive_skb() and napi_gro_frags(), including other
protocols using the same helpers. Linear headers and private fragments
retain their existing fast paths.
Codex assisted with review of the supplied report, reproducer and draft
fix, related-path analysis, and this changelog. The patched
net/core/gro.o builds with W=1 using the supplied x86-64 configuration,
allyesconfig and allmodconfig. The fix was checked by code-path analysis;
the reproducer and kernel selftests have not been run on a booted
patched kernel.
The issue was found by an LLM.
Fixes: dff0b0161ad5 ("net: gro: parse ipv6 ext headers without frag0 invalidation")
Cc: stable@kernel.org
Signed-off-by: Kyle Zeng <kylebot@openai.com>
---
I have a reproducer for this issue.
v2:
- add Fixes tag
- explain that the issue was found by LLM
v1: https://lore.kernel.org/netdev/20261030042212.73949-1-kylebot@openai.com/
net/core/gro.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/core/gro.c b/net/core/gro.c
index 1b033855a20d..d6cf2d497934 100644
--- a/net/core/gro.c
+++ b/net/core/gro.c
@@ -413,7 +413,8 @@ static inline void skb_gro_reset_offset(struct sk_buff *skb, u32 nhoff)
headlen = skb_headlen(skb);
NAPI_GRO_CB(skb)->frag0 = skb->data;
NAPI_GRO_CB(skb)->frag0_len = headlen;
- if (headlen)
+ /* Shared fragments must be pulled into the linear head before parsing. */
+ if (headlen || skb_has_shared_frag(skb))
return;
pinfo = skb_shinfo(skb);
base-commit: 2a500a04d6f969318c05f46aedb6e73fc1963a00
--
2.55.0.openai.911.g06873a30d2f3
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-31 5:07 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-31 5:07 [PATCH net v2] net: gro: avoid parsing headers from shared fragments Kyle Zeng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®