* [PATCH] net: gro: don't chain linear parts larger than gso_size into frag_list
@ 2026-10-13 10:24 Sorah Fukumori
2026-10-13 11:03 ` Eric Dumazet
0 siblings, 1 reply; 3+ messages in thread
From: Sorah Fukumori @ 2026-10-13 10:24 UTC (permalink / raw)
To: netdev, davem, edumazet, kuba, pabeni
Cc: horms, willemb, lixiaoyan, linux-kernel, Sorah Fukumori
skb_gro_receive() chains an skb into the frag_list of the held packet
when its payload cannot be attached as page frags, i.e. when its head
is not a page fragment and still holds payload. Since commit
5eddb24901ee ("gro: add support of (hw)gro packets to gro stack"), that
skb may itself be a GSO packet whose linear part holds several
gso_size segments. skb_segment() cannot split the linear part of a
frag_list member across segments, so segmenting the aggregate in
software, e.g. when forwarding it to a device without NETIF_F_FRAGLIST,
hits
BUG_ON(skb_headlen(list_skb) > len);
Fully linear GSO packets come from generic XDP. When the program does
not support frags, netif_skb_check_for_xdp() linearizes any nonlinear
skb with pskb_expand_head() and skb_linearize() and keeps its GSO
metadata. GRO on the device runs before generic XDP, so each aggregate
passed by the program carries all of its payload in a kmalloc'ed head.
A tunnel that decapsulates these packets and runs GRO again through
gro_cells then builds the bad frag_list. This was first seen on a
router that forwards TCP received over VXLAN, with a non-frags XDP
program attached in SKB mode to the underlying bond because one slave
lacks native XDP:
kernel BUG at net/core/skbuff.c:4917!
RIP: 0010:skb_segment+0xbb6/0xf40
Call Trace:
tcp_gso_segment
ipv6_gso_segment
skb_mac_gso_segment
__skb_gso_segment
validate_xmit_skb
__dev_queue_xmit
ip6_output
ip6_sublist_rcv_finish
ipv6_list_rcv
netif_receive_skb_list_internal
gro_complete
dev_gro_receive
gro_receive_skb
gro_cell_poll
__napi_poll
net_rx_action
It reproduces with three network namespaces: TCP sent over VXLAN on an
IPv6 veth link to a router namespace that has an XDP_PASS program
without frags support attached to the underlay veth in generic mode
and GRO enabled on its VXLAN device, and forwards to a veth with
tx-scatter-gather-fraglist disabled.
Refuse the merge when the linear part to be chained exceeds the held
packet's gso_size. tcp_gro_receive() then flushes the held packet and
the skb starts a new GRO packet as its head, whose linear length
skb_segment() handles.
Fixes: 5eddb24901ee ("gro: add support of (hw)gro packets to gro stack")
Cc: stable@vger.kernel.org
Assisted-by: claude-opus-5-5
Signed-off-by: Sorah Fukumori <her@sorah.jp>
---
net/core/gro.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/core/gro.c b/net/core/gro.c
index 29b4d02bf519..ff828a3dce3c 100644
--- a/net/core/gro.c
+++ b/net/core/gro.c
@@ -187,6 +187,10 @@ int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb)
}
merge:
+ /* skb_segment() cannot split the linear part of a frag_list member. */
+ if (unlikely(headlen > offset + skb_shinfo(p)->gso_size))
+ return -E2BIG;
+
/* sk ownership - if any - completely transferred to the aggregated packet */
skb->destructor = NULL;
skb->sk = NULL;
--
2.55.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] net: gro: don't chain linear parts larger than gso_size into frag_list
2026-10-13 10:24 [PATCH] net: gro: don't chain linear parts larger than gso_size into frag_list Sorah Fukumori
@ 2026-10-13 11:03 ` Eric Dumazet
2026-10-13 13:00 ` Sorah Fukumori
0 siblings, 1 reply; 3+ messages in thread
From: Eric Dumazet @ 2026-10-13 11:03 UTC (permalink / raw)
To: Sorah Fukumori
Cc: netdev, davem, kuba, pabeni, horms, willemb, lixiaoyan, linux-kernel
Le mar. 13 oct. 2026 à 12:25, Sorah Fukumori <her@sorah.jp> a écrit :
>
> skb_gro_receive() chains an skb into the frag_list of the held packet
> when its payload cannot be attached as page frags, i.e. when its head
> is not a page fragment and still holds payload.
>
> Fully linear GSO packets come from generic XDP. When the program does
> not support frags, netif_skb_check_for_xdp() linearizes any nonlinear
> skb with pskb_expand_head() and skb_linearize() and keeps its GSO
> metadata.
On Tue, Oct 13, 2026 at 12:24 PM Sorah Fukumori <her@sorah.jp> wrote:
>
> skb_gro_receive() chains an skb into the frag_list of the held packet
> when its payload cannot be attached as page frags, i.e. when its head
> is not a page fragment and still holds payload.
[...]
> Fully linear GSO packets come from generic XDP. When the program does
> not support frags, netif_skb_check_for_xdp() linearizes any nonlinear
> skb with pskb_expand_head() and skb_linearize() and keeps its GSO
> metadata.
I think the problem is a bit wider than what is described here.
skb_gro_receive() also reaches the merge: label from the head_frag
branch, when the frags do not fit:
if (nr_frags + 1 + skbinfo->nr_frags > MAX_SKB_FRAGS)
goto merge;
A GSO skb with a page frag head holding more than gso_size bytes of
payload is then chained in frag_list as well, and the BUG_ON() in
skb_segment() does not care about head_frag.
It seems an XDP program with frags support in generic mode could
get there: skb_pp_cow_data() builds a head_frag skb with up to
about one page of linear data, the rest in page frags, and
skb_copy_header() keeps the GSO metadata. Two such 64KB packets
can not share a single frags[] array.
Have you tried this variant with your reproducer ?
Your patch handles it anyway, since the check is done at the merge:
label, but the changelog should mention it.
>
> Fixes: 5eddb24901ee ("gro: add support of (hw)gro packets to gro stack")
> Cc: stable@vger.kernel.org
> Assisted-by: claude-opus-5-5
> Signed-off-by: Sorah Fukumori <her@sorah.jp>
> ---
> net/core/gro.c | 4 ++++
> 1 file changed, 4 insertions(+)
Please use [PATCH net] in the subject for fixes.
The fix itself looks good to me, thanks.
Reviewed-by: Eric Dumazet <edumazet@kernel.org>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] net: gro: don't chain linear parts larger than gso_size into frag_list
2026-10-13 11:03 ` Eric Dumazet
@ 2026-10-13 13:00 ` Sorah Fukumori
0 siblings, 0 replies; 3+ messages in thread
From: Sorah Fukumori @ 2026-10-13 13:00 UTC (permalink / raw)
To: Eric Dumazet
Cc: netdev, davem, kuba, pabeni, horms, willemb, lixiaoyan, linux-kernel
Hi,
On Tue, 13 Oct 2026, at 8:03 PM, Eric Dumazet wrote:
> It seems an XDP program with frags support in generic mode could
> get there: skb_pp_cow_data() builds a head_frag skb with up to
> about one page of linear data, the rest in page frags, and
> skb_copy_header() keeps the GSO metadata. Two such 64KB packets
> can not share a single frags[] array.
>
> Have you tried this variant with your reproducer ?
Thanks, I haven't. I tried to reproduce that variant under various gro_max_size/RPS configuration, but I couldn't repro on my qemu+veth based script.
Will send out v2 with updated commit message soon, and sorry about missing `net` prefix in the subject, it will be included in v2.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-13 13:00 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-13 10:24 [PATCH] net: gro: don't chain linear parts larger than gso_size into frag_list Sorah Fukumori
2026-10-13 11:03 ` Eric Dumazet
2026-10-13 13:00 ` Sorah Fukumori
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®