Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 2609

kernel-2.6.18-194.11.1.el5.src.rpm

From: Peter Staubach <staubach@redhat.com>
Date: Tue, 21 Apr 2009 14:07:40 -0400
Subject: [nfs] large writes rejected when sec=krb5i/p specified
Message-id: 49EE0B6C.6050406@redhat.com
O-Subject: [RHEL-5.4 PATCH] BZ486756 nfs server rejecting large writes when sec=krb5i/p is specified
Bugzilla: 486756
RH-Acked-by: Jeff Layton <jlayton@redhat.com>
RH-Acked-by: Rik van Riel <riel@redhat.com>

Hi.

Attached is a patch to address bz486756, "nfs server rejecting
large writes when sec=krb5i/p is specified".  This is a problem
which was introduced by some slightly overzealous checking to
ensure that the amount of data in an NFS WRITE request matches
the amount of data that should be contained in the NFS WRITE
request.  The original checking worked for AUTH_SYS authenticated
requests, but does not work for RPCSEC_GSS authenticated requests
because they pad the request differently.

This was tested using the Connectathon testsuite to generate
WRITE requests against the modified server.

    Thanx...

       ps

diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 57d91b0..a35ab34 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -401,8 +401,12 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
 	 * Round the length of the data which was specified up to
 	 * the next multiple of XDR units and then compare that
 	 * against the length which was actually received.
+	 *
+	 * Note that when RPCSEC/GSS (for example) is used, the
+	 * data buffer can be padded so dlen might be larger
+	 * than required.  It must never be smaller.
 	 */
-	if (dlen != XDR_QUADLEN(len) * 4)
+	if (dlen < XDR_QUADLEN(len) * 4)
 		return 0;
 
 	if (args->count > NFSSVC_MAXBLKSIZE) {
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 8d8c85a..913e161 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -304,8 +304,12 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
 	 * Round the length of the data which was specified up to
 	 * the next multiple of XDR units and then compare that
 	 * against the length which was actually received.
+	 *
+	 * Note that when RPCSEC/GSS (for example) is used, the
+	 * data buffer can be padded so dlen might be larger
+	 * than required.  It must never be smaller.
 	 */
-	if (dlen != XDR_QUADLEN(len) * 4)
+	if (dlen < XDR_QUADLEN(len) * 4)
 		return 0;
 
 	args->vec[0].iov_base = (void*)p;