mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [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®