Sophie

Sophie

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

kernel-2.6.18-194.11.1.el5.src.rpm

From: Peter Staubach <staubach@redhat.com>
Date: Fri, 29 May 2009 09:51:57 -0400
Subject: [nfs] v4: 'r'/'w' perms for user do not work on client
Message-id: 4A1FE87D.8010701@redhat.com
O-Subject: [PATCH RHEL-5.4] BZ502244 'r' and 'w' permission for user do not work on NFSv4 client
Bugzilla: 502244
RH-Acked-by: Jerome Marchand <jmarchan@redhat.com>
RH-Acked-by: Jeff Layton <jlayton@redhat.com>

Hi.

Attached is a patch to address bz502244, "'r' and 'w' permission
for user do not work on NFSv4 client".  The problem described is
a situation where the owner of a file can access a file, even if
the file modes indicate that the owner should not have access to
the file.  In particular, the owner can read from and write to a
file with mode 0.

The problem is really on the NFS server side.  It is the entity
that is used to calculate access permissions.  In this case, the
NFSv4 share and deny modes were being incorrectly used and the
decision for whether the owner should be allowed to override the
permissions was being incorrectly made.

The owner is allowed to override the permissions for i/o being
done to an open file.  This is done so that the sequence: open,
chmod(0), write, succeeds instead of fails due to the chmod(0)
in the middle.

This was tested by running the testcase as described in the
bug report and also by writing a small test program to ensure
that system calls that should work, continue to work, and that
system calls that should fail, do fail.

    Thanx...

       ps

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index da5e7d4..3740220 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -69,20 +69,21 @@ fh_dup2(struct svc_fh *dst, struct svc_fh *src)
 }
 
 static int
-do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
+do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh,
+		struct nfsd4_open *open, int accmode)
 {
-	int accmode, status;
+	int status;
 
 	if (open->op_truncate &&
-		!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
+	    !(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
 		return nfserr_inval;
 
-	accmode = MAY_NOP;
 	if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
-		accmode = MAY_READ;
-	if (open->op_share_deny & NFS4_SHARE_ACCESS_WRITE)
+		accmode |= MAY_READ;
+	if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
 		accmode |= (MAY_WRITE | MAY_TRUNC);
-	accmode |= MAY_OWNER_OVERRIDE;
+	if (open->op_share_deny & NFS4_SHARE_DENY_WRITE)
+		accmode |= MAY_WRITE;
 
 	status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
 
@@ -132,7 +133,7 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
 				&resfh.fh_handle.fh_base,
 				resfh.fh_handle.fh_size);
 
-		status = do_open_permission(rqstp, current_fh, open);
+		status = do_open_permission(rqstp, current_fh, open, MAY_NOP);
 	}
 
 	fh_put(&resfh);
@@ -163,7 +164,8 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_
 	open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
 		(open->op_iattr.ia_size == 0);
 
-	status = do_open_permission(rqstp, current_fh, open);
+	status = do_open_permission(rqstp, current_fh, open,
+				MAY_OWNER_OVERRIDE);
 
 	return status;
 }