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

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Sat Jan 2 02:07:12 UTC 2016


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

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

commit b9a267a5fe1e98c19c8ef1e18264250bc1cbd9b8
Author: Ben Hutchings <ben at decadent.org.uk>
Date:   Sat Jan 2 01:54:06 2016 +0000

    udp: properly support MSG_PEEK with truncated buffers (Closes: #808293, regression in 3.2.72)
---
 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                              |   2 +
 4 files changed, 200 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 53d2f20..47911bd 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,8 @@ linux (3.2.73-2+deb7u2) UNRELEASED; urgency=medium
   * KEYS: Fix race between read and revoke (CVE-2015-7550)
   * [x86] KVM: Reload pit counters for all channels when restoring state
     (CVE-2015-7513)
+  * udp: properly support MSG_PEEK with truncated buffers
+    (Closes: #808293, regression in 3.2.72)
 
  -- Ben Hutchings <ben at decadent.org.uk>  Sun, 27 Dec 2015 19:23:43 +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..391e135
--- /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 127500d724f8c43f452610c9080444eedb5eaa6c.  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
+@@ -2134,8 +2134,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
+@@ -709,7 +709,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.
+  *
+@@ -719,14 +718,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
+@@ -5198,7 +5198,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
+@@ -1207,7 +1207,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
+@@ -479,7 +479,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
+@@ -383,8 +383,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
+@@ -185,8 +185,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..f910fd8
--- /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 3.2: 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
+@@ -1172,6 +1172,7 @@ int udp_recvmsg(struct kiocb *iocb, stru
+ 	int peeked;
+ 	int err;
+ 	int is_udplite = IS_UDPLITE(sk);
++	bool checksum_valid = false;
+ 	bool slow;
+ 
+ 	if (flags & MSG_ERRQUEUE)
+@@ -1197,11 +1198,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
+@@ -344,6 +344,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;
+ 	bool slow;
+ 
+@@ -375,11 +376,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 b/debian/patches/series
index f52caab..76452f7 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1186,3 +1186,5 @@ bugfix/all/pptp-verify-sockaddr_len-in-pptp_bind-and-pptp_conne.patch
 bugfix/all/bluetooth-validate-socket-address-length-in-sco_sock.patch
 bugfix/all/keys-fix-race-between-read-and-revoke.patch
 bugfix/x86/KVM-x86-Reload-pit-counters-for-all-channels-when-re.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