Commit 4ce56133 authored by J. Bruce Fields's avatar J. Bruce Fields Committed by Ben Hutchings

nfsd: don't fail unchecked creates of non-special files

commit 9dc4e6c4 upstream.

Allow a v3 unchecked open of a non-regular file succeed as if it were a
lookup; typically a client in such a case will want to fall back on a
local open, so succeeding and giving it the filehandle is more useful
than failing with nfserr_exist, which makes it appear that nothing at
all exists by that name.

Similarly for v4, on an open-create, return the same errors we would on
an attempt to open a non-regular file, instead of returning
nfserr_exist.

This fixes a problem found doing a v4 open of a symlink with
O_RDONLY|O_CREAT, which resulted in the current client returning EEXIST.

Thanks also to Trond for analysis.
Reported-by: default avatarOrion Poplawski <orion@cora.nwra.com>
Tested-by: default avatarOrion Poplawski <orion@cora.nwra.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
[bwh: Backported to 3.2: use &resfh, not resfh]
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 20564838
...@@ -231,15 +231,15 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o ...@@ -231,15 +231,15 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
*/ */
if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0) if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0)
open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS | open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS |
FATTR4_WORD1_TIME_MODIFY); FATTR4_WORD1_TIME_MODIFY);
} else { } else {
status = nfsd_lookup(rqstp, current_fh, status = nfsd_lookup(rqstp, current_fh,
open->op_fname.data, open->op_fname.len, &resfh); open->op_fname.data, open->op_fname.len, &resfh);
fh_unlock(current_fh); fh_unlock(current_fh);
if (status)
goto out;
status = nfsd_check_obj_isreg(&resfh);
} }
if (status)
goto out;
status = nfsd_check_obj_isreg(&resfh);
if (status) if (status)
goto out; goto out;
......
...@@ -1439,7 +1439,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -1439,7 +1439,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
switch (createmode) { switch (createmode) {
case NFS3_CREATE_UNCHECKED: case NFS3_CREATE_UNCHECKED:
if (! S_ISREG(dchild->d_inode->i_mode)) if (! S_ISREG(dchild->d_inode->i_mode))
err = nfserr_exist; goto out;
else if (truncp) { else if (truncp) {
/* in nfsv4, we need to treat this case a little /* in nfsv4, we need to treat this case a little
* differently. we don't want to truncate the * differently. we don't want to truncate the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment