aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-05-11 17:03:19 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2018-05-21 14:30:10 -0400
commit3819bb0d79f50b05910db5bdc6d9ef512184e3b1 (patch)
tree471f4930a15a15c6e482fc0284fef824e02dcee4 /fs/nfsd/vfs.c
parent9c3e9025a3f7ed25c99a0add8af65431c8043800 (diff)
nfsd: vfs_mkdir() might succeed leaving dentry negative unhashed
That can (and does, on some filesystems) happen - ->mkdir() (and thus vfs_mkdir()) can legitimately leave its argument negative and just unhash it, counting upon the lookup to pick the object we'd created next time we try to look at that name. Some vfs_mkdir() callers forget about that possibility... Acked-by: J. Bruce Fields <bfields@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 2410b093a2e6..b0555d7d8200 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1201,6 +1201,28 @@ nfsd_create_locked(struct svc_rqst *rqstp, struct svc_fh *fhp,
1201 break; 1201 break;
1202 case S_IFDIR: 1202 case S_IFDIR:
1203 host_err = vfs_mkdir(dirp, dchild, iap->ia_mode); 1203 host_err = vfs_mkdir(dirp, dchild, iap->ia_mode);
1204 if (!host_err && unlikely(d_unhashed(dchild))) {
1205 struct dentry *d;
1206 d = lookup_one_len(dchild->d_name.name,
1207 dchild->d_parent,
1208 dchild->d_name.len);
1209 if (IS_ERR(d)) {
1210 host_err = PTR_ERR(d);
1211 break;
1212 }
1213 if (unlikely(d_is_negative(d))) {
1214 dput(d);
1215 err = nfserr_serverfault;
1216 goto out;
1217 }
1218 dput(resfhp->fh_dentry);
1219 resfhp->fh_dentry = dget(d);
1220 err = fh_update(resfhp);
1221 dput(dchild);
1222 dchild = d;
1223 if (err)
1224 goto out;
1225 }
1204 break; 1226 break;
1205 case S_IFCHR: 1227 case S_IFCHR:
1206 case S_IFBLK: 1228 case S_IFBLK: