net: gso: clear the GSO state of the last output segment

skb_segment() clears gso_size on the last output of a group which holds one
MSS or less, but leaves gso_segs and gso_type as the grouping set them, so
the tail is still counted as the whole group.  Readers which take gso_segs
without testing gso_size first, such as the ECT statistics in ip_rcv_core()
and tp->rcv_ooopack in tcp_rcv_established(), see that stale count, and a
re-segmented output reaches them when a veth or bridge port delivers it back
into the receive path.

Clear gso_size, gso_segs and gso_type together with skb_gso_reset().

Suggested-by: Willem de Bruijn <willemb@google.com>
Assisted-by: LLM
Signed-off-by: Wang Zhan <wang.zhan@smartx.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20261008100651.2534957-5-wang.zhan@smartx.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Wang Zhan 2026-10-08 18:06:49 +08:00 committed by Paolo Abeni
parent c4076626ba
commit 335a0378a7

View File

@ -5129,7 +5129,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
}
if (tail->len - doffset <= gso_size)
skb_shinfo(tail)->gso_size = 0;
skb_gso_reset(tail);
else if (tail != segs)
skb_shinfo(tail)->gso_segs = DIV_ROUND_UP(tail->len - doffset, gso_size);
}