mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Trond Myklebust <trond.myklebust@fys.uio.no>
To: Ingo Saitz <Ingo.Saitz@stud.uni-hannover.de>,
	Chris Wright <chrisw@osdl.org>
Cc: linux-kernel@vger.kernel.org
Subject: Re: Linux 2.6.15.5 - NFS client broken
Date: Wed, 01 Mar 2006 18:33:38 -0800	[thread overview]
Message-ID: <1141266818.26382.46.camel@netapplinux-10.connectathon.org> (raw)
In-Reply-To: <20060302021758.GA24337@schwan.subspace.exe>

[-- Attachment #1: Type: text/plain, Size: 822 bytes --]

On Thu, 2006-03-02 at 03:17 +0100, Ingo Saitz wrote:
> Moin
> 
> Compiling 2.6.15.5 aborts with the following error:
> 
>   CC [M]  fs/nfs/direct.o
> fs/nfs/direct.c: In function ‘nfs_get_user_pages’:
> fs/nfs/direct.c:110: warning: implicit declaration of function ‘nfs_free_user_pages’
> fs/nfs/direct.c: At top level:
> fs/nfs/direct.c:127: warning: conflicting types for ‘nfs_free_user_pages’
> fs/nfs/direct.c:127: error: static declaration of ‘nfs_free_user_pages’ follows non-static declaration
> fs/nfs/direct.c:110: error: previous implicit declaration of ‘nfs_free_user_pages’ was here
> make[3]: *** [fs/nfs/direct.o] Error 1
> 
> Attached .config

Here is the full patch I sent to Chris the other day. That first hunk
must have gotten lost somewhere...

Cheers,
 Trond

[-- Attachment #2: linux-2.6.16-01-fix_oopsable_odirect.dif --]
[-- Type: text/plain, Size: 2463 bytes --]

Author: Trond Myklebust <Trond.Myklebust@netapp.com>
NFS: Fix a potential panic in O_DIRECT

Based on an original patch by Mike O'Connor and Greg Banks of SGI.

Mike states:

A normal user can panic an NFS client and cause a local DoS with
'judicious'(?) use of O_DIRECT. Any O_DIRECT write to an NFS file where the
user buffer starts with a valid mapped page and contains an unmapped page,
will crash in this way.  I haven't followed the code, but O_DIRECT reads
with similar user buffers will probably also crash albeit in different
ways.

Details:  when nfs_get_user_pages() calls get_user_pages(), it detects
and correctly handles get_user_pages() returning an error, which happens
if the first page covered by the user buffer's address range is unmapped.
However, if the first page is mapped but some subsequent page isn't,
get_user_pages() will return a positive number which is less than the
number of pages requested (this behaviour is sort of analagous to a
short write() call and appears to be intentional).  nfs_get_user_pages()
doesn't detect this and hands off the array of pages (whose last few
elements are random rubbish from the newly allocated array memory) to
it's caller, whence they go to nfs_direct_write_seg(), which then totally
ignores the nr_pages it's given, and calculates its own idea of how many
pages are in the array from the user buffer length.  Needless to say,
when it comes to transmit those uninitialised page* pointers, we see
a crash in the network stack.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
---

 fs/nfs/direct.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 04ab2fc..4e9b3a1 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -57,6 +57,7 @@
 #define NFSDBG_FACILITY		NFSDBG_VFS
 #define MAX_DIRECTIO_SIZE	(4096UL << PAGE_SHIFT)
 
+static void nfs_free_user_pages(struct page **pages, int npages, int do_dirty);
 static kmem_cache_t *nfs_direct_cachep;
 
 /*
@@ -107,6 +108,15 @@ nfs_get_user_pages(int rw, unsigned long
 					page_count, (rw == READ), 0,
 					*pages, NULL);
 		up_read(&current->mm->mmap_sem);
+		/*
+		 * If we got fewer pages than expected from get_user_pages(),
+		 * the user buffer runs off the end of a mapping; return EFAULT.
+		 */
+		if (result >= 0 && result < page_count) {
+			nfs_free_user_pages(*pages, result, 0);
+			*pages = NULL;
+			result = -EFAULT;
+		}
 	}
 	return result;
 }

  reply	other threads:[~2006-03-02  2:33 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-03-02  2:17 Ingo Saitz
2006-03-02  2:33 ` Trond Myklebust [this message]
2006-03-02  6:18   ` Chris Wright

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=1141266818.26382.46.camel@netapplinux-10.connectathon.org \
    --to=trond.myklebust@fys.uio.no \
    --cc=Ingo.Saitz@stud.uni-hannover.de \
    --cc=chrisw@osdl.org \
    --cc=linux-kernel@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®