]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
udp: Fix UDP length on last GSO_PARTIAL segment
authorGal Pressman <gal@nvidia.com>
Mon, 18 May 2026 06:22:50 +0000 (09:22 +0300)
committerJakub Kicinski <kuba@kernel.org>
Wed, 20 May 2026 22:03:47 +0000 (15:03 -0700)
Following the cited commit, __udp_gso_segment() writes single MSS length
in the UDP header.
The cited patch doesn't account for the fact that the last segment could
be a GSO skb by itself. This could happen when the size of the packet is
a multiple of MSS, hence the first segment is also the last one (there
is no need for a remainder skb).

When the post-loop segment is a GSO skb, assign the single MSS length in
the UDP header.

Fixes: b10b446ce7ad ("udp: gso: Use single MSS length in UDP header for GSO_PARTIAL")
Reported-by: Matthew Schwartz <matthew.schwartz@linux.dev>
Closes: https://lore.kernel.org/all/6c3fb15e-711d-4b8d-b152-e03d9b05293f@linux.dev/
Tested-by: Matthew Schwartz <matthew.schwartz@linux.dev>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Gal Pressman <gal@nvidia.com>
Link: https://patch.msgid.link/20260518062250.3019914-3-gal@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv4/udp_offload.c

index 2578aa7f9ff9391317866e17306ac022a2ec6d55..29651b1a0bc704f46aafb67bc42f81ec3defca40 100644 (file)
@@ -590,9 +590,12 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
                uh = udp_hdr(seg);
        }
 
-       /* last packet can be partial gso_size, account for that in checksum */
-       newlen = htons(skb_tail_pointer(seg) - skb_transport_header(seg) +
-                      seg->data_len);
+       /* Unless skb fits perfectly as GSO_PARTIAL, the trailing
+        * segment may not be full MSS, account for that in the checksum
+        */
+       if (!skb_is_gso(seg))
+               newlen = htons(skb_tail_pointer(seg) -
+                              skb_transport_header(seg) + seg->data_len);
        check = csum16_add(csum16_sub(uh->check, uh->len), newlen);
 
        uh->len = newlen;