Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > eab357269fb8735c5e1a2938e6c77cae > files > 2152

kernel-2.6.18-164.10.1.el5.src.rpm

From: Sachin S. Prabhu <sprabhu@redhat.com>
Date: Wed, 11 Feb 2009 20:36:40 +0000
Subject: [nfs] memory corruption in nfs3_xdr_setaclargs
Message-id: 499336D8.3080003@redhat.com
O-Subject: Re: [RHEL 5.4 PATCH]BZ 479432: Memory corruption in nfs3_xdr_setaclargs()
Bugzilla: 479432
RH-Acked-by: Steve Dickson <SteveD@redhat.com>
RH-Acked-by: Peter Staubach <staubach@redhat.com>
RH-Acked-by: Jeff Layton <jlayton@redhat.com>

A mistake in calculating the space left in the header in nfs3_xdr_setaclargs()
can cause memory corruption on client when setting a large number of acls.

Reproducer:
Reproducer available at
https://bugzilla.redhat.com/show_bug.cgi?id=479432#c31
This will cause the client machine to crash.

Upstream:
The problem also affects the upstream kernel. A patch has been posted to
linux-nfs and has been accepted by Trond Myklebust.
http://thread.gmane.org/gmane.linux.nfs/24219
This has not been included in Trond's git tree yet. We expect this to make it in
2.6.9-30.

Description:

A change in call_header changes the value req->rq_snd_buf->head[0]->iov_len to
reflect the exact size of the header.
[PATCH] RPC: Ensure XDR iovec length is initialized correctly in call_header
334ccfd545bba9690515f2c5c167d5adb161989b

The iov_len is set to the size of the header in  call_header().
req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);

nfs3_xdr_setaclargs() depends on the older behavior and uses this value when
calculating the number of ACLs it can fit into the header.

        /* put as much of the acls into head as possible. */
        len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
        len -= len_in_head;
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));

Since at this stage, iov_len < base, len_in_head will always be set to len.  For
a large number of ACLs, this will end up over-writing other parts of memory on
the nfs client.

The following patch(customer provided) which set len_in_head to 0 was tested
with the reproducer and was found to fix the problem.

This is an urgent issue at IBM since the build cluster for bluegene requires ACL
support for their build process.

Sachin Prabhu

diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 43ca3d3..949bb40 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -710,7 +710,10 @@ nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p,
 	*p++ = htonl(args->mask);
 	base = (char *)p - (char *)buf->head->iov_base;
 	/* put as much of the acls into head as possible. */
-	len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
+	if (buf->head->iov_len > base)
+		len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
+	else
+		len_in_head = 0;
 	len -= len_in_head;
 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));