|
| 1 | +From: Jan Niehusmann <jan@gondor.com> |
| 2 | +Date: Fri, 14 Apr 2017 21:26:27 +0200 |
| 3 | +Subject: udp: properly support MSG_PEEK with truncated buffers |
| 4 | + |
| 5 | +Add upstream patch to fix CVE-2016-10229 |
| 6 | + |
| 7 | +diff --git a/target/linux/generic/patches-3.18/001-udp-properly-support-MSG_PEEK-with-truncated-buffers.patch b/target/linux/generic/patches-3.18/001-udp-properly-support-MSG_PEEK-with-truncated-buffers.patch |
| 8 | +new file mode 100644 |
| 9 | +index 0000000000000000000000000000000000000000..16edc8c8da4ce8edf3ce1b5c2a56d543f9658897 |
| 10 | +--- /dev/null |
| 11 | ++++ b/target/linux/generic/patches-3.18/001-udp-properly-support-MSG_PEEK-with-truncated-buffers.patch |
| 12 | +@@ -0,0 +1,97 @@ |
| 13 | ++From 69335972b1c1c9bd7597fc6080b6eb1bd3fbf774 Mon Sep 17 00:00:00 2001 |
| 14 | ++From: Eric Dumazet <edumazet@google.com> |
| 15 | ++Date: Wed, 30 Dec 2015 08:51:12 -0500 |
| 16 | ++Subject: [PATCH] udp: properly support MSG_PEEK with truncated buffers |
| 17 | ++ |
| 18 | ++[ Upstream commit 197c949e7798fbf28cfadc69d9ca0c2abbf93191 ] |
| 19 | ++ |
| 20 | ++Backport of this upstream commit into stable kernels : |
| 21 | ++89c22d8c3b27 ("net: Fix skb csum races when peeking") |
| 22 | ++exposed a bug in udp stack vs MSG_PEEK support, when user provides |
| 23 | ++a buffer smaller than skb payload. |
| 24 | ++ |
| 25 | ++In this case, |
| 26 | ++skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), |
| 27 | ++ msg->msg_iov); |
| 28 | ++returns -EFAULT. |
| 29 | ++ |
| 30 | ++This bug does not happen in upstream kernels since Al Viro did a great |
| 31 | ++job to replace this into : |
| 32 | ++skb_copy_and_csum_datagram_msg(skb, sizeof(struct udphdr), msg); |
| 33 | ++This variant is safe vs short buffers. |
| 34 | ++ |
| 35 | ++For the time being, instead reverting Herbert Xu patch and add back |
| 36 | ++skb->ip_summed invalid changes, simply store the result of |
| 37 | ++udp_lib_checksum_complete() so that we avoid computing the checksum a |
| 38 | ++second time, and avoid the problematic |
| 39 | ++skb_copy_and_csum_datagram_iovec() call. |
| 40 | ++ |
| 41 | ++This patch can be applied on recent kernels as it avoids a double |
| 42 | ++checksumming, then backported to stable kernels as a bug fix. |
| 43 | ++ |
| 44 | ++Signed-off-by: Eric Dumazet <edumazet@google.com> |
| 45 | ++Acked-by: Herbert Xu <herbert@gondor.apana.org.au> |
| 46 | ++Signed-off-by: David S. Miller <davem@davemloft.net> |
| 47 | ++Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| 48 | ++--- |
| 49 | ++ net/ipv4/udp.c | 6 ++++-- |
| 50 | ++ net/ipv6/udp.c | 6 ++++-- |
| 51 | ++ 2 files changed, 8 insertions(+), 4 deletions(-) |
| 52 | ++ |
| 53 | ++diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c |
| 54 | ++index 2a5d388..ee26711 100644 |
| 55 | ++--- a/net/ipv4/udp.c |
| 56 | +++++ b/net/ipv4/udp.c |
| 57 | ++@@ -1252,6 +1252,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, |
| 58 | ++ int peeked, off = 0; |
| 59 | ++ int err; |
| 60 | ++ int is_udplite = IS_UDPLITE(sk); |
| 61 | +++ bool checksum_valid = false; |
| 62 | ++ bool slow; |
| 63 | ++ |
| 64 | ++ if (flags & MSG_ERRQUEUE) |
| 65 | ++@@ -1277,11 +1278,12 @@ try_again: |
| 66 | ++ */ |
| 67 | ++ |
| 68 | ++ if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { |
| 69 | ++- if (udp_lib_checksum_complete(skb)) |
| 70 | +++ checksum_valid = !udp_lib_checksum_complete(skb); |
| 71 | +++ if (!checksum_valid) |
| 72 | ++ goto csum_copy_err; |
| 73 | ++ } |
| 74 | ++ |
| 75 | ++- if (skb_csum_unnecessary(skb)) |
| 76 | +++ if (checksum_valid || skb_csum_unnecessary(skb)) |
| 77 | ++ err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), |
| 78 | ++ msg->msg_iov, copied); |
| 79 | ++ else { |
| 80 | ++diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c |
| 81 | ++index 7d01116..143e6c7 100644 |
| 82 | ++--- a/net/ipv6/udp.c |
| 83 | +++++ b/net/ipv6/udp.c |
| 84 | ++@@ -388,6 +388,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, |
| 85 | ++ int peeked, off = 0; |
| 86 | ++ int err; |
| 87 | ++ int is_udplite = IS_UDPLITE(sk); |
| 88 | +++ bool checksum_valid = false; |
| 89 | ++ int is_udp4; |
| 90 | ++ bool slow; |
| 91 | ++ |
| 92 | ++@@ -419,11 +420,12 @@ try_again: |
| 93 | ++ */ |
| 94 | ++ |
| 95 | ++ if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) { |
| 96 | ++- if (udp_lib_checksum_complete(skb)) |
| 97 | +++ checksum_valid = !udp_lib_checksum_complete(skb); |
| 98 | +++ if (!checksum_valid) |
| 99 | ++ goto csum_copy_err; |
| 100 | ++ } |
| 101 | ++ |
| 102 | ++- if (skb_csum_unnecessary(skb)) |
| 103 | +++ if (checksum_valid || skb_csum_unnecessary(skb)) |
| 104 | ++ err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), |
| 105 | ++ msg->msg_iov, copied); |
| 106 | ++ else { |
| 107 | ++-- |
| 108 | ++2.1.4 |
| 109 | ++ |
0 commit comments