All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Hutchings <ben@decadent.org.uk>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: akpm@linux-foundation.org, "Jeff Layton" <jlayton@redhat.com>,
	"Steve French" <smfrench@gmail.com>,
	"Al Viro" <viro@zeniv.linux.org.uk>,
	"Pavel Shilovsky" <piastry@etersoft.ru>
Subject: [PATCH 3.2 17/18] cifs: ensure that uncached writes handle unmapped areas correctly
Date: Mon, 07 Apr 2014 00:35:48 +0100	[thread overview]
Message-ID: <lsq.1396827348.486893332@decadent.org.uk> (raw)
In-Reply-To: <lsq.1396827347.462803115@decadent.org.uk>

3.2.57-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Jeff Layton <jlayton@redhat.com>

commit 5d81de8e8667da7135d3a32a964087c0faf5483f upstream.

It's possible for userland to pass down an iovec via writev() that has a
bogus user pointer in it. If that happens and we're doing an uncached
write, then we can end up getting less bytes than we expect from the
call to iov_iter_copy_from_user. This is CVE-2014-0069

cifs_iovec_write isn't set up to handle that situation however. It'll
blindly keep chugging through the page array and not filling those pages
with anything useful. Worse yet, we'll later end up with a negative
number in wdata->tailsz, which will confuse the sending routines and
cause an oops at the very least.

Fix this by having the copy phase of cifs_iovec_write stop copying data
in this situation and send the last write as a short one. At the same
time, we want to avoid sending a zero-length write to the server, so
break out of the loop and set rc to -EFAULT if that happens. This also
allows us to handle the case where no address in the iovec is valid.

[Note: Marking this for stable on v3.4+ kernels, but kernels as old as
       v2.6.38 may have a similar problem and may need similar fix]

Reviewed-by: Pavel Shilovsky <piastry@etersoft.ru>
Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <smfrench@gmail.com>
[bwh: Backported to 3.2:
 - Adjust context
 - s/nr_pages/npages/
 - s/wdata->pages/pages/
 - In case of an error with no data copied, we must kunmap() page 0,
   but in neither case should we free anything else]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 fs/cifs/file.c | 37 ++++++++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)

--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2107,7 +2107,7 @@ cifs_iovec_write(struct file *file, cons
 {
 	unsigned int written;
 	unsigned long num_pages, npages, i;
-	size_t copied, len, cur_len;
+	size_t bytes, copied, len, cur_len;
 	ssize_t total_written = 0;
 	struct kvec *to_send;
 	struct page **pages;
@@ -2165,17 +2165,44 @@ cifs_iovec_write(struct file *file, cons
 	do {
 		size_t save_len = cur_len;
 		for (i = 0; i < npages; i++) {
-			copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE);
+			bytes = min_t(const size_t, cur_len, PAGE_CACHE_SIZE);
 			copied = iov_iter_copy_from_user(pages[i], &it, 0,
-							 copied);
+							 bytes);
 			cur_len -= copied;
 			iov_iter_advance(&it, copied);
 			to_send[i+1].iov_base = kmap(pages[i]);
 			to_send[i+1].iov_len = copied;
+			/*
+			 * If we didn't copy as much as we expected, then that
+			 * may mean we trod into an unmapped area. Stop copying
+			 * at that point. On the next pass through the big
+			 * loop, we'll likely end up getting a zero-length
+			 * write and bailing out of it.
+			 */
+			if (copied < bytes)
+				break;
 		}
 
 		cur_len = save_len - cur_len;
 
+		/*
+		 * If we have no data to send, then that probably means that
+		 * the copy above failed altogether. That's most likely because
+		 * the address in the iovec was bogus. Set the rc to -EFAULT,
+		 * free anything we allocated and bail out.
+		 */
+		if (!cur_len) {
+			kunmap(pages[0]);
+			rc = -EFAULT;
+			break;
+		}
+
+		/*
+		 * i + 1 now represents the number of pages we actually used in
+		 * the copy phase above.
+		 */
+		npages = i + 1;
+
 		do {
 			if (open_file->invalidHandle) {
 				rc = cifs_reopen_file(open_file, false);


  parent reply	other threads:[~2014-04-06 23:40 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-06 23:35 [PATCH 3.2 00/18] 3.2.57-rc1 review Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 01/18] Input: synaptics - add manual min/max quirk Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 02/18] Input: synaptics - add manual min/max quirk for ThinkPad X240 Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 14/18] net: asix: add missing flag to struct driver_info Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 10/18] deb-pkg: Fix building for MIPS big-endian or ARM OABI Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 04/18] ext4: atomically set inode->i_flags in ext4_set_inode_flags() Ben Hutchings
2014-04-06 23:35 ` Ben Hutchings [this message]
2014-04-07  1:41   ` [PATCH 3.2 17/18] cifs: ensure that uncached writes handle unmapped areas correctly Ben Hutchings
2014-04-07 13:45     ` Raphael Geissert
2014-04-07 19:14       ` Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 07/18] net: add and use skb_gso_transport_seglen() Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 12/18] asix: asix_rx_fixup surgery to reduce skb truesizes Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 18/18] s390: fix kernel crash due to linkage stack instructions Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 03/18] staging: speakup: Prefix set_mask_bits() symbol Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 13/18] net: asix: handle packets crossing URB boundaries Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 06/18] ipc/msg: fix race around refcount Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 05/18] netfilter: nf_conntrack_dccp: fix skb_header_pointer API usages Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 16/18] KVM: VMX: fix use after free of vmx->loaded_vmcs Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 09/18] deb-pkg: use KCONFIG_CONFIG instead of .config file directly Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 11/18] deb-pkg: Fix cross-building linux-headers package Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 15/18] KVM: MMU: handle invalid root_hpa at __direct_map Ben Hutchings
2014-04-06 23:35 ` [PATCH 3.2 08/18] net: ip, ipv6: handle gso skbs in forwarding path Ben Hutchings
2014-04-07  1:42 ` [PATCH 3.2 00/18] 3.2.57-rc1 review Ben Hutchings
2014-04-07  3:55 ` Guenter Roeck
2014-04-07 12:30   ` Ben Hutchings

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=lsq.1396827348.486893332@decadent.org.uk \
    --to=ben@decadent.org.uk \
    --cc=akpm@linux-foundation.org \
    --cc=jlayton@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=piastry@etersoft.ru \
    --cc=smfrench@gmail.com \
    --cc=stable@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.