summaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorOleg Drokin <green@linuxhacker.ru>2016-07-14 23:20:22 -0400
committerJ. Bruce Fields <bfields@redhat.com>2016-08-04 17:11:46 -0400
commit7eed34f18d9f0f96f51bfb73d649a51a20857eb0 (patch)
tree32d4f2332f9305226f81d60f262842f5b9250b35 /fs/nfsd
parentc7995f8a70c441146e128934d775d4ba0e4d7bc4 (diff)
downloadop-kernel-dev-7eed34f18d9f0f96f51bfb73d649a51a20857eb0.zip
op-kernel-dev-7eed34f18d9f0f96f51bfb73d649a51a20857eb0.tar.gz
nfsd: Make creates return EEXIST instead of EACCES
When doing a create (mkdir/mknod) on a name, it's worth checking the name exists first before returning EACCES in case the directory is not writeable by the user. This makes return values on the client more consistent regardless of whenever the entry there is cached in the local cache or not. Another positive side effect is certain programs only expect EEXIST in that case even despite POSIX allowing any valid error to be returned. Signed-off-by: Oleg Drokin <green@linuxhacker.ru> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4proc.c6
-rw-r--r--fs/nfsd/vfs.c11
2 files changed, 15 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index e0c15f8..9d7e1ed 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -605,8 +605,12 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
fh_init(&resfh, NFS4_FHSIZE);
+ /*
+ * We just check that parent is accessible here, nfsd_* do their
+ * own access permission checks
+ */
status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR,
- NFSD_MAY_CREATE);
+ NFSD_MAY_EXEC);
if (status)
return status;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 6fbd81e..fda4f86 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1161,7 +1161,11 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (isdotent(fname, flen))
goto out;
- err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
+ /*
+ * Even though it is a create, first let's see if we are even allowed
+ * to peek inside the parent
+ */
+ err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
if (err)
goto out;
@@ -1211,6 +1215,11 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out;
}
+ /* Now let's see if we actually have permissions to create */
+ err = nfsd_permission(rqstp, fhp->fh_export, dentry, NFSD_MAY_CREATE);
+ if (err)
+ goto out;
+
if (!(iap->ia_valid & ATTR_MODE))
iap->ia_mode = 0;
iap->ia_mode = (iap->ia_mode & S_IALLUGO) | type;
OpenPOWER on IntegriCloud