mirror of
https://github.com/team-infusion-developers/android_kernel_samsung_msm8976.git
synced 2024-11-07 04:09:21 +00:00
udp: properly support MSG_PEEK with truncated buffers
Backport of this upstream commit into stable kernels : 89c22d8c3b27 ("net: Fix skb csum races when peeking") exposed a bug in udp stack vs MSG_PEEK support, when user provides a buffer smaller than skb payload. In this case, skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov); returns -EFAULT. This bug does not happen in upstream kernels since Al Viro did a great job to replace this into : skb_copy_and_csum_datagram_msg(skb, sizeof(struct udphdr), msg); This variant is safe vs short buffers. For the time being, instead reverting Herbert Xu patch and add back skb->ip_summed invalid changes, simply store the result of udp_lib_checksum_complete() so that we avoid computing the checksum a second time, and avoid the problematic skb_copy_and_csum_datagram_iovec() call. This patch can be applied on recent kernels as it avoids a double checksumming, then backported to stable kernels as a bug fix. Signed-off-by: Eric Dumazet <edumazet@google.com> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net> [d-cagle@codeaurora.org: Resolve trivial merge conflicts] Git-repo: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git Git-commit: 197c949e7798fbf28cfadc69d9ca0c2abbf93191 Change-Id: I70f19a362f627bd2d9d8e10e31bbcdb4b0600792 Signed-off-by: Dennis Cagle <d-cagle@codeaurora.org>
This commit is contained in:
parent
067816447b
commit
533ee96a28
2 changed files with 8 additions and 4 deletions
|
@ -1215,6 +1215,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
|||
int peeked, off = 0;
|
||||
int err;
|
||||
int is_udplite = IS_UDPLITE(sk);
|
||||
bool checksum_valid = false;
|
||||
bool slow;
|
||||
|
||||
if (flags & MSG_ERRQUEUE)
|
||||
|
@ -1240,11 +1241,12 @@ try_again:
|
|||
*/
|
||||
|
||||
if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {
|
||||
if (udp_lib_checksum_complete(skb))
|
||||
checksum_valid = !udp_lib_checksum_complete(skb);
|
||||
if (!checksum_valid)
|
||||
goto csum_copy_err;
|
||||
}
|
||||
|
||||
if (skb_csum_unnecessary(skb))
|
||||
if (checksum_valid || skb_csum_unnecessary(skb))
|
||||
err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
|
||||
msg->msg_iov, copied);
|
||||
else {
|
||||
|
|
|
@ -370,6 +370,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
|
|||
int peeked, off = 0;
|
||||
int err;
|
||||
int is_udplite = IS_UDPLITE(sk);
|
||||
bool checksum_valid = false;
|
||||
int is_udp4;
|
||||
bool slow;
|
||||
|
||||
|
@ -401,11 +402,12 @@ try_again:
|
|||
*/
|
||||
|
||||
if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {
|
||||
if (udp_lib_checksum_complete(skb))
|
||||
checksum_valid = !udp_lib_checksum_complete(skb);
|
||||
if (!checksum_valid)
|
||||
goto csum_copy_err;
|
||||
}
|
||||
|
||||
if (skb_csum_unnecessary(skb))
|
||||
if (checksum_valid || skb_csum_unnecessary(skb))
|
||||
err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
|
||||
msg->msg_iov, copied);
|
||||
else {
|
||||
|
|
Loading…
Reference in a new issue