[linux] 01/01: udp: properly support MSG_PEEK with truncated buffers (Closes: #808293, regression in 2.6.32.69)

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Sat Jan 2 02:06:50 UTC 2016


This is an automated email from the git hooks/post-receive script.

benh pushed a commit to branch squeeze-security
in repository linux.

commit 849f7353f683b2a63804da8476feaa2256b6cee9
Author: Ben Hutchings <ben at decadent.org.uk>
Date:   Sat Jan 2 01:53:16 2016 +0000

    udp: properly support MSG_PEEK with truncated buffers (Closes: #808293, regression in 2.6.32.69)
---
 debian/changelog                                   |   2 +
 ...ument-to-skb_copy_and_csum_datagram_iovec.patch | 108 +++++++++++++++++++++
 ...y-support-msg_peek-with-truncated-buffers.patch |  88 +++++++++++++++++
 debian/patches/series/48squeeze18                  |   2 +
 4 files changed, 200 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index e9f89d5..3b71262 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -3,6 +3,8 @@ linux-2.6 (2.6.32-48squeeze18) UNRELEASED; urgency=medium
   * net: add validation for the socket syscall protocol argument (CVE-2015-8543)
   * bluetooth: Validate socket address length in sco_sock_bind() (CVE-2015-8575)
   * KEYS: Fix race between read and revoke (CVE-2015-7550)
+  * udp: properly support MSG_PEEK with truncated buffers
+    (Closes: #808293, regression in 2.6.32.69)
 
  -- Ben Hutchings <ben at decadent.org.uk>  Sun, 27 Dec 2015 20:06:05 +0000
 
diff --git a/debian/patches/bugfix/all/revert-net-add-length-argument-to-skb_copy_and_csum_datagram_iovec.patch b/debian/patches/bugfix/all/revert-net-add-length-argument-to-skb_copy_and_csum_datagram_iovec.patch
new file mode 100644
index 0000000..c47ee65
--- /dev/null
+++ b/debian/patches/bugfix/all/revert-net-add-length-argument-to-skb_copy_and_csum_datagram_iovec.patch
@@ -0,0 +1,108 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Sat, 02 Jan 2016 01:11:55 +0000
+Subject: Revert "net: add length argument to skb_copy_and_csum_datagram_iovec"
+Bug-Debian: https://bugs.debian.org/808293
+
+This reverts commit c507639ba963bb47e3f515670a7cace76af76ab6.  That fixed
+the problem of buffer over-reads introduced by backporting commit
+89c22d8c3b27 ("net: Fix skb csum races when peeking"), but resulted in
+incorrect checksumming for short reads.  It will be replaced with a
+complete fix.
+
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+---
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -1775,8 +1775,7 @@ extern int	       skb_copy_datagram_iove
+ 					       int size);
+ extern int	       skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
+ 							int hlen,
+-							struct iovec *iov,
+-							int len);
++							struct iovec *iov);
+ extern int	       skb_copy_datagram_from_iovec(struct sk_buff *skb,
+ 						    int offset,
+ 						    const struct iovec *from,
+--- a/net/core/datagram.c
++++ b/net/core/datagram.c
+@@ -693,7 +693,6 @@ EXPORT_SYMBOL(__skb_checksum_complete);
+  *	@skb: skbuff
+  *	@hlen: hardware length
+  *	@iov: io vector
+- *	@len: amount of data to copy from skb to iov
+  *
+  *	Caller _must_ check that skb will fit to this iovec.
+  *
+@@ -703,14 +702,11 @@ EXPORT_SYMBOL(__skb_checksum_complete);
+  *			   can be modified!
+  */
+ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
+-				     int hlen, struct iovec *iov, int len)
++				     int hlen, struct iovec *iov)
+ {
+ 	__wsum csum;
+ 	int chunk = skb->len - hlen;
+ 
+-	if (chunk > len)
+-		chunk = len;
+-
+ 	if (!chunk)
+ 		return 0;
+ 
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -4985,7 +4985,7 @@ static int tcp_copy_to_iovec(struct sock
+ 		err = skb_copy_datagram_iovec(skb, hlen, tp->ucopy.iov, chunk);
+ 	else
+ 		err = skb_copy_and_csum_datagram_iovec(skb, hlen,
+-						       tp->ucopy.iov, chunk);
++						       tp->ucopy.iov);
+ 
+ 	if (!err) {
+ 		tp->ucopy.len -= chunk;
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -975,7 +975,7 @@ try_again:
+ 	else {
+ 		err = skb_copy_and_csum_datagram_iovec(skb,
+ 						       sizeof(struct udphdr),
+-						       msg->msg_iov, copied);
++						       msg->msg_iov);
+ 
+ 		if (err == -EINVAL)
+ 			goto csum_copy_err;
+--- a/net/ipv6/raw.c
++++ b/net/ipv6/raw.c
+@@ -476,7 +476,7 @@ static int rawv6_recvmsg(struct kiocb *i
+ 			goto csum_copy_err;
+ 		err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+ 	} else {
+-		err = skb_copy_and_csum_datagram_iovec(skb, 0, msg->msg_iov, copied);
++		err = skb_copy_and_csum_datagram_iovec(skb, 0, msg->msg_iov);
+ 		if (err == -EINVAL)
+ 			goto csum_copy_err;
+ 	}
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -233,8 +233,7 @@ try_again:
+ 		err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
+ 					      msg->msg_iov, copied       );
+ 	else {
+-		err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr),
+-						       msg->msg_iov, copied);
++		err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
+ 		if (err == -EINVAL)
+ 			goto csum_copy_err;
+ 	}
+--- a/net/rxrpc/ar-recvmsg.c
++++ b/net/rxrpc/ar-recvmsg.c
+@@ -184,8 +184,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, st
+ 						      msg->msg_iov, copy);
+ 		} else {
+ 			ret = skb_copy_and_csum_datagram_iovec(skb, offset,
+-							       msg->msg_iov,
+-							       copy);
++							       msg->msg_iov);
+ 			if (ret == -EINVAL)
+ 				goto csum_copy_error;
+ 		}
diff --git a/debian/patches/bugfix/all/udp-properly-support-msg_peek-with-truncated-buffers.patch b/debian/patches/bugfix/all/udp-properly-support-msg_peek-with-truncated-buffers.patch
new file mode 100644
index 0000000..1594cd3
--- /dev/null
+++ b/debian/patches/bugfix/all/udp-properly-support-msg_peek-with-truncated-buffers.patch
@@ -0,0 +1,88 @@
+From: Eric Dumazet <edumazet at google.com>
+Date: Wed, 30 Dec 2015 08:51:12 -0500
+Subject: udp: properly support MSG_PEEK with truncated  buffers
+Bug-Debian: https://bugs.debian.org/808293
+Origin: http://article.gmane.org/gmane.linux.kernel.stable/159132
+
+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 at google.com>
+[bwh: Backported to 2.6.32: adjust context]
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+---
+ net/ipv4/udp.c |    6 ++++--
+ net/ipv6/udp.c |    6 ++++--
+ 2 files changed, 8 insertions(+), 4 deletions(-)
+
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -941,6 +941,7 @@ int udp_recvmsg(struct kiocb *iocb, stru
+ 	int peeked;
+ 	int err;
+ 	int is_udplite = IS_UDPLITE(sk);
++	bool checksum_valid = false;
+ 
+ 	if (flags & MSG_ERRQUEUE)
+ 		return ip_recv_error(sk, msg, len, addr_len);
+@@ -965,11 +966,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 {
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -198,6 +198,7 @@ int udpv6_recvmsg(struct kiocb *iocb, st
+ 	int peeked;
+ 	int err;
+ 	int is_udplite = IS_UDPLITE(sk);
++	bool checksum_valid = false;
+ 	int is_udp4;
+ 
+ 	if (flags & MSG_ERRQUEUE)
+@@ -225,11 +226,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 {
diff --git a/debian/patches/series/48squeeze18 b/debian/patches/series/48squeeze18
index 23b0906..96b328d 100644
--- a/debian/patches/series/48squeeze18
+++ b/debian/patches/series/48squeeze18
@@ -1,3 +1,5 @@
 + bugfix/all/net-add-validation-for-the-socket-syscall-protocol-a.patch
 + bugfix/all/bluetooth-validate-socket-address-length-in-sco_sock.patch
 + bugfix/all/keys-fix-race-between-read-and-revoke.patch
++ bugfix/all/revert-net-add-length-argument-to-skb_copy_and_csum_datagram_iovec.patch
++ bugfix/all/udp-properly-support-msg_peek-with-truncated-buffers.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux.git



More information about the Kernel-svn-changes mailing list