https://lore.kernel.org/netdev/20200728015505.37830-1-de...@microsoft.com/
-- You received this bug notification because you are a member of Kernel Packages, which is subscribed to linux in Ubuntu. https://bugs.launchpad.net/bugs/1888715 Title: UDP data corruption caused by buggy udp_recvmsg() -> skb_copy_and_csum_datagram_msg() Status in linux package in Ubuntu: Incomplete Bug description: The Xenial v4.4 kernel (https://kernel.ubuntu.com/git/ubuntu/ubuntu- xenial.git/tag/?h=Ubuntu-4.4.0-184.214) lacks this upstream bug fix("make skb_copy_datagram_msg() et.al. preserve ->msg_iter on erro" https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3278682123811dd8ef07de5eb701fc4548fcebf2); as a result, the v4.4 kernel can deliver corrupt data to the application when a corrupt packet is closely followed by a valid packet, and actually the UDP payload of the corrupt packet is delivered to the application with the "from IP/Port" of the valid packet, so this is actually a security vulnerability that can be used to trick the application to think the corrupt packet’s payload is sent from the valid packet’s IP address/port, i.e. a source IP based security authentication mechanism can be bypassed. Details: For a packet longer than 76 bytes (see line 3951, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/skbuff.h?h=v5.8-rc6#n3948), Linux delays the UDP checksum verification until the application invokes the syscall recvmsg(). In the recvmsg() syscall handler, while Linux is copying the UDP payload to the application’s memory, it calculates the UDP checksum. If the calculated checksum doesn’t match the received checksum, Linux drops the corrupt UDP packet, and then starts to process the next packet (if any), and if the next packet is valid (i.e. the checksum is correct), Linux will copy the valid UDP packet's payload to the application’s receiver buffer. The bug is: before Linux starts to copy the valid UDP packet, the data structure used to track how many more bytes should be copied to the application memory is not reset to what it was when the application just entered the kernel by the syscall! Consequently, only a small portion or none of the valid packet’s payload is copied to the application’s receive buffer, and later when the application exits from the kernel, actually most of the application’s receive buffer contains the payload of the corrupt packet while recvmsg() returns the size of the UDP payload of the valid packet. Note: this is actually a security vulnerability that can be used to trick the application to think the corrupt packet’s payload is sent from the valid packet’s IP address/port -- so a source IP based security authentication mechanism can be bypassed. The bug was fixed in this 2017 patch “make skb_copy_datagram_msg() et.al. preserve ->msg_iter on error (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3278682123811dd8ef07de5eb701fc4548fcebf2)”, but unluckily the patch is only backported to the upstream v4.9+ kernels. I'm reporting this bug to request the bugfix to be backported to the v4.4 Xenial kernel, which is still used by some users and has not been EOL'ed (https://ubuntu.com/about/release-cycle). I have the below one-line workaround patch to force the recvmsg() syscall handler to return to the userspace when Linux detects a corrupt UDP packet, so the application will invoke the syscall again to receive the next good UDP packet: --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1367,6 +1367,7 @@ csum_copy_err: /* starting over for a new packet, but check if we need to yield */ cond_resched(); msg->msg_flags &= ~MSG_TRUNC; + return -EAGAIN; goto try_again; } Note: the patch may not work well with blocking sockets, for which typically the application doesn’t expect an error of -EAGAIN. I guess it would be safer to return -EINTR instead. To manage notifications about this bug go to: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1888715/+subscriptions -- Mailing list: https://launchpad.net/~kernel-packages Post to : kernel-packages@lists.launchpad.net Unsubscribe : https://launchpad.net/~kernel-packages More help : https://help.launchpad.net/ListHelp