Skip to contentSkip to conversation

nfsd3: Check write permission after checking existence

PATCH In review Ross Lagerwall 2 participants 3 messages Aug 9, 2014 – Aug 11, 2014

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 nfsd3: Check write permission after checking existence

When creating a file that already exists in a read-only directory with O_EXCL, the NFSv3 server returns EACCES rather than EEXIST (which local files and the NFSv4 server return). Fix this by checking the MAY_CREATE permission only if the file does not exist. Since this already happens in do_nfsd_create, the check in nfsd3_proc_create can simply be removed.

---
 fs/nfsd/nfs3proc.c | 5 -----
 1 file changed, 5 deletions(-)
fs/nfsd/nfs3proc.c +0 -5
index 4012899..8ebd4ac 100644
@@ -227,11 +227,6 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
 	newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
 	attr   = &argp->attrs;
 
-	/* Get the directory inode */
-	nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_CREATE);
-	if (nfserr)
-		RETURN_STATUS(nfserr);
-
 	/* Unfudge the mode bits */
 	attr->ia_mode &= ~S_IFMT;
 	if (!(attr->ia_valid & ATTR_MODE)) { 
Signature · 1 line
2.0.3
#1 lore raw
Quoted 5 lines · Ross Lagerwall

When creating a file that already exists in a read-only directory with O_EXCL, the NFSv3 server returns EACCES rather than EEXIST (which local files and the NFSv4 server return). Fix this by checking the MAY_CREATE permission only if the file does not exist. Since this already happens in do_nfsd_create, the check in nfsd3_proc_create can simply be removed.

Thanks.

Quoted 1 line

From a look at the history I believe the server has behaved this way

since the beginning. Is this creating a practical problem for you? How did you notice it?

Inclined to apply it just for consistency as you suggest. And because it removes some unnecessary code. But as a low priority: for 3.18 and not stable.

--b.

Quoted 25 lines
---
 fs/nfsd/nfs3proc.c | 5 -----
 1 file changed, 5 deletions(-)
fs/nfsd/nfs3proc.c +0 -5
index 4012899..8ebd4ac 100644
@@ -227,11 +227,6 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
 	newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
 	attr   = &argp->attrs;
 
-	/* Get the directory inode */
-	nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_CREATE);
-	if (nfserr)
-		RETURN_STATUS(nfserr);
-
 	/* Unfudge the mode bits */
 	attr->ia_mode &= ~S_IFMT;
 	if (!(attr->ia_valid & ATTR_MODE)) { 
Signature · 1 line
2.0.3
#2 lore raw
Quoted 7 lines · J. Bruce Fields
Quoted 5 lines · Ross Lagerwall

When creating a file that already exists in a read-only directory with O_EXCL, the NFSv3 server returns EACCES rather than EEXIST (which local files and the NFSv4 server return). Fix this by checking the MAY_CREATE permission only if the file does not exist. Since this already happens in do_nfsd_create, the check in nfsd3_proc_create can simply be removed.

Quoted 5 lines

Thanks.

From a look at the history I believe the server has behaved this way since the beginning. Is this creating a practical problem for you? How did you notice it?

I help maintain GNOME's gvfs and so I have a bunch of test programs which I run to check for conformance. I noticed that:
gvfs-save /mnt/dir/file
fails with a permission denied error when file is on an NFSv3 mount and dir is read-only. Basically, gvfs-save first tries to create the file. If it already exists, then it just truncates it. But on NFSv3, the first creation generates a permission denied error so the operation is aborted.

Not really a practical problem, but it is possible to see this with various real-world programs which do a similar dance when saving like this:
open(path, O_WRONLY|O_CREAT|O_EXCL)
if EEXIST:
open(path, O_WRONLY|O_CREAT|O_TRUNC)
else:
bail()

(For Linux NFS clients, the kernel does its own client-side caching so if you do:
ls /mnt/dir; gvfs-save /mnt/dir/file
it magically works!)

Quoted 5 lines

Inclined to apply it just for consistency as you suggest. And because it removes some unnecessary code. But as a low priority: for 3.18 and not stable.

OK, your decision. That is OK with me.

Cheers,

Signature · 1 line
Ross Lagerwall