6.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Anderson sean.anderson@linux.dev
[ Upstream commit e8a63d473b49011a68a748aea1c8aefa046ebacf ]
Padding is not included in UDP and TCP checksums. Therefore, reduce the length of the checksummed data to include only the data in the IP payload. This fixes spurious reported checksum failures like
rx: pkt: sport=33000 len=26 csum=0xc850 verify=0xf9fe pkt: bad csum
Technically it is possible for there to be trailing bytes after the UDP data but before the Ethernet padding (e.g. if sizeof(ip) + sizeof(udp) + udp.len < ip.len). However, we don't generate such packets.
Fixes: 91a7de85600d ("selftests/net: add csum offload test") Signed-off-by: Sean Anderson sean.anderson@linux.dev Reviewed-by: Willem de Bruijn willemb@google.com Link: https://patch.msgid.link/20240906210743.627413-1-sean.anderson@linux.dev Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- tools/testing/selftests/net/lib/csum.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/net/lib/csum.c b/tools/testing/selftests/net/lib/csum.c index b9f3fc3c3426..e0a34e5e8dd5 100644 --- a/tools/testing/selftests/net/lib/csum.c +++ b/tools/testing/selftests/net/lib/csum.c @@ -654,10 +654,16 @@ static int recv_verify_packet_ipv4(void *nh, int len) { struct iphdr *iph = nh; uint16_t proto = cfg_encap ? IPPROTO_UDP : cfg_proto; + uint16_t ip_len;
if (len < sizeof(*iph) || iph->protocol != proto) return -1;
+ ip_len = ntohs(iph->tot_len); + if (ip_len > len || ip_len < sizeof(*iph)) + return -1; + + len = ip_len; iph_addr_p = &iph->saddr; if (proto == IPPROTO_TCP) return recv_verify_packet_tcp(iph + 1, len - sizeof(*iph)); @@ -669,16 +675,22 @@ static int recv_verify_packet_ipv6(void *nh, int len) { struct ipv6hdr *ip6h = nh; uint16_t proto = cfg_encap ? IPPROTO_UDP : cfg_proto; + uint16_t ip_len;
if (len < sizeof(*ip6h) || ip6h->nexthdr != proto) return -1;
+ ip_len = ntohs(ip6h->payload_len); + if (ip_len > len - sizeof(*ip6h)) + return -1; + + len = ip_len; iph_addr_p = &ip6h->saddr;
if (proto == IPPROTO_TCP) - return recv_verify_packet_tcp(ip6h + 1, len - sizeof(*ip6h)); + return recv_verify_packet_tcp(ip6h + 1, len); else - return recv_verify_packet_udp(ip6h + 1, len - sizeof(*ip6h)); + return recv_verify_packet_udp(ip6h + 1, len); }
/* return whether auxdata includes TP_STATUS_CSUM_VALID */