diff options
| author | Mingming Cao <mmc@linux.ibm.com> | 2026-10-13 11:29:26 -0700 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2026-10-20 15:37:50 -0700 |
| commit | 9486c89a8e157cedecfb561c3d86053e654d32ab (patch) | |
| tree | a9bd597b1907ab09ade201c92b682236af45d1fe /tools/lib/python | |
| parent | 3f872b34368c7c1d2a8900950e0fee4cb4dd9a34 (diff) | |
ibmveth: check headers in the RX large send and checksum helpers
ibmveth_rx_mss_helper() and ibmveth_rx_csum_helper() trust the IP and
TCP headers of received frames, which come from another partition on
the virtual LAN.
The worst case is an IPv4 frame with ihl 0 and iph->check 0xffff: the
checksum helper calls ip_fast_csum(iph, 0), and the ppc64 version
loops ihl - 1 times on an unsigned count, reading up to 16 GiB in
softirq: a long stall, or an oops once the read leaves mapped memory.
Both helpers also read and write header fields past the end of a short
frame. The large send helper takes the segment size from the TCP
checksum field and gso_segs from a TCP header length it never checks,
and treats an IPv4 TCP fragment as a large send, which can zero two of
its bytes; the checksum helper can write a checksum into a later
fragment's payload.
The ihl problem dates from the first commit in Fixes:, the large send
helper from the second, and the checksum helper from the third.
Before using a header, check that it fits the frame, that the IPv4 ihl
is at least 5, and that an IPv4 TCP frame is not a fragment. In the
large send helper, also require a TCP doff of at least 5, TCP payload
within the IP length, and an IP length equal to the frame length:
Ethernet padding or other bytes past the IP length would otherwise
stay in a bridged or switched frame, which the stack does not trim,
and be segmented but not counted in gso_segs. Compute gso_segs from
the IP length, and keep the segment size at or above TCP_MIN_GSO_SIZE,
as virtio_net_hdr_to_skb() does since commit c27c449d455a ("virtio-net:
Ensure that TCP packets don't overflow gso_segs"), and below
GSO_BY_FRAGS, which virtio rejects. With the headers checked and
gso_segs computed, the skb is not marked SKB_GSO_DODGY, which would
also keep it from hardware TSO on the egress device.
A frame that fails a check is passed up unchanged, without the GSO
fields or CHECKSUM_UNNECESSARY, so nothing downstream trusts its
segment count or checksum. The skb is linear, so the checks use
skb_headlen(); pskb_may_pull() could reallocate the head under the
helpers' header pointers.
Add KUnit cases for both helpers: valid IPv4 and IPv6 large sends, the
segment size clamp, and refused frames. With any one of the ihl, doff,
IP length, TCP payload, fragment or clamp checks, or the checksum
helper's IPv4 options, IPv6 header or TCP header length checks,
removed, a case fails; without the checksum helper's ihl check,
ip_fast_csum() oopses on qemu.
Found by the Sashiko review of the previous version of this series and
confirmed by code inspection and the KUnit cases above. Tested with
KUnit on qemu pseries (ppc64le) and on a POWER10 LPAR with iperf3 large
sends over IPv4 and IPv6 at MTU 1500 and 9000, threaded NAPI and busy
polling, with no new drops or InCsumErrors. No kernel selftests cover
ibmveth.
Fixes: 9c7e8bc584f5 ("ibmveth: Add support for Large Receive Offload")
Fixes: 7b5967389f5a ("ibmveth: set correct gso_size and gso_type")
Fixes: 66aa0678efc2 ("ibmveth: Support to enable LSO/CSO for Trunk VEA.")
Signed-off-by: Mingming Cao <mmc@linux.ibm.com>
Link: https://patch.msgid.link/20261013182926.30417-10-mmc@linux.ibm.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'tools/lib/python')
0 files changed, 0 insertions, 0 deletions
