0097-udp-properly-support-MSG_PEEK-with-truncated-buffers.patch 3.8 KB

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