Re: [PATCH net v2] net: gro: don't chain linear parts larger than gso_size into frag_list

From: Jason Xing

Date: Mon Oct 19 2026 - 05:34:30 EST


On Tue, Oct 13, 2026 at 9:17 PM Sorah Fukumori <her@xxxxxxxx> wrote:
>
> skb_gro_receive() chains an skb into the frag_list of the held packet
> when its payload cannot be attached as page frags: when its head is
> not a page fragment and still holds payload, or when its head and
> frags would overflow the frags[] array of the last packet. 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.
>
> A program with frags support in generic mode gives similar packets.
> skb_pp_cow_data() rebuilds the skb with up to about a page of linear
> data in a page_pool head_frag and keeps the GSO metadata, so once
> frags[] is full the next such packet is chained through frag_list
> with more than gso_size bytes in its head as well.
>
> 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@xxxxxxxxxxxxxxx
> Assisted-by: claude-opus-5-5
> Signed-off-by: Sorah Fukumori <her@xxxxxxxx>

Reviewed-by: Jason Xing <kerneljasonxing@xxxxxxxxx>

Thanks!