Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

udplite: fix partial checksum initialization

Since UDP-Lite is always using checksum, the following path is
triggered when calculating pseudo header for it:

udp4_csum_init() or udp6_csum_init()
skb_checksum_init_zero_check()
__skb_checksum_validate_complete()

The problem can appear if skb->len is less than CHECKSUM_BREAK. In
this particular case __skb_checksum_validate_complete() also invokes
__skb_checksum_complete(skb). If UDP-Lite is using partial checksum
that covers only part of a packet, the function will return bad
checksum and the packet will be dropped.

It can be fixed if we skip skb_checksum_init_zero_check() and only
set the required pseudo header checksum for UDP-Lite with partial
checksum before udp4_csum_init()/udp6_csum_init() functions return.

Fixes: ed70fcfcee95 ("net: Call skb_checksum_init in IPv4")
Fixes: e4f45b7f40bd ("net: Call skb_checksum_init in IPv6")
Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Alexey Kodanev and committed by
David S. Miller
15f35d49 da279887

+11
+1
include/net/udplite.h
··· 64 64 UDP_SKB_CB(skb)->cscov = cscov; 65 65 if (skb->ip_summed == CHECKSUM_COMPLETE) 66 66 skb->ip_summed = CHECKSUM_NONE; 67 + skb->csum_valid = 0; 67 68 } 68 69 69 70 return 0;
+5
net/ipv4/udp.c
··· 2024 2024 err = udplite_checksum_init(skb, uh); 2025 2025 if (err) 2026 2026 return err; 2027 + 2028 + if (UDP_SKB_CB(skb)->partial_cov) { 2029 + skb->csum = inet_compute_pseudo(skb, proto); 2030 + return 0; 2031 + } 2027 2032 } 2028 2033 2029 2034 /* Note, we are only interested in != 0 or == 0, thus the
+5
net/ipv6/ip6_checksum.c
··· 73 73 err = udplite_checksum_init(skb, uh); 74 74 if (err) 75 75 return err; 76 + 77 + if (UDP_SKB_CB(skb)->partial_cov) { 78 + skb->csum = ip6_compute_pseudo(skb, proto); 79 + return 0; 80 + } 76 81 } 77 82 78 83 /* To support RFC 6936 (allow zero checksum in UDP/IPV6 for tunnels)