Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1126

kernel-2.6.18-238.el5.src.rpm

From: Jiri Olsa <jolsa@redhat.com>
Date: Tue, 13 Jul 2010 12:47:55 -0400
Subject: [fs] nfs: fix bug in nfsd4 read_buf
Message-id: <1279025275-6967-1-git-send-email-jolsa@redhat.com>
Patchwork-id: 26836
O-Subject: [PATCH RHEL5] BZ 612035 - CVE-2010-2521 kernel: nfsd4: bug in read_buf
Bugzilla: 612035
CVE: CVE-2010-2521
RH-Acked-by: Dean Nelson <dnelson@redhat.com>

Bugzilla: 612035
https://bugzilla.redhat.com/show_bug.cgi?id=612035

Description:
============
When read_buf is called to move over to the next page in the pagelist
of an NFSv4 request, it sets argp->end to essentially a random
number, certainly not an address within the page which argp->p now
points to.  So subsequent calls to READ_BUF will think there is much
more than a page of spare space (the cast to u32 ensures an unsigned
comparison) so we can expect to fall off the end of the second
page.

Upstream status:
================
- nfsd4: bug in read_buf
  commit 2bc3c1179c781b359d4f2f3439cb3df72afc17fc
  Author: Neil Brown <neilb@suse.de>

Brew:
=====
https://brewweb.devel.redhat.com/taskinfo?taskID=2589512

Tested:
=======
booted, exported nfs mount

Signed-off-by: Jarod Wilson <jarod@redhat.com>

diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 810d9ff..8786256 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -164,10 +164,10 @@ static u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
 	argp->p = page_address(argp->pagelist[0]);
 	argp->pagelist++;
 	if (argp->pagelen < PAGE_SIZE) {
-		argp->end = p + (argp->pagelen>>2);
+		argp->end = argp->p + (argp->pagelen>>2);
 		argp->pagelen = 0;
 	} else {
-		argp->end = p + (PAGE_SIZE>>2);
+		argp->end = argp->p + (PAGE_SIZE>>2);
 		argp->pagelen -= PAGE_SIZE;
 	}
 	memcpy(((char*)p)+avail, argp->p, (nbytes - avail));
@@ -1033,10 +1033,10 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 			argp->p = page_address(argp->pagelist[0]);
 			argp->pagelist++;
 			if (argp->pagelen < PAGE_SIZE) {
-				argp->end = p + (argp->pagelen>>2);
+				argp->end = argp->p + (argp->pagelen>>2);
 				argp->pagelen = 0;
 			} else {
-				argp->end = p + (PAGE_SIZE>>2);
+				argp->end = argp->p + (PAGE_SIZE>>2);
 				argp->pagelen -= PAGE_SIZE;
 			}
 		}