aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfsfh.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2016-07-19 17:33:04 -0400
committerJ. Bruce Fields <bfields@redhat.com>2016-08-04 17:11:48 -0400
commite75b23f9e323b1e0759619c39d5a9f7a3a5d9d2c (patch)
treef87cc0dee5dbb4f22fda8ab3c92dba6e83b75a29 /fs/nfsd/nfsfh.c
parent12391d07230ec7368269227207b961b2dcb34180 (diff)
nfsd: check d_can_lookup in fh_verify of directories
Create and other nfsd ops generally assume we can call lookup_one_len on inodes with S_IFDIR set. Al says that this assumption isn't true in general, though it should be for the filesystem objects nfsd sees. Add a check just to make sure our assumption isn't violated. Remove a couple checks for i_op->lookup in create code. Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfsfh.c')
-rw-r--r--fs/nfsd/nfsfh.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 27250e279c37..cfe7500d5847 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -59,14 +59,20 @@ static int nfsd_acceptable(void *expv, struct dentry *dentry)
59 * the write call). 59 * the write call).
60 */ 60 */
61static inline __be32 61static inline __be32
62nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, umode_t requested) 62nfsd_mode_check(struct svc_rqst *rqstp, struct dentry *dentry,
63 umode_t requested)
63{ 64{
64 mode &= S_IFMT; 65 umode_t mode = d_inode(dentry)->i_mode & S_IFMT;
65 66
66 if (requested == 0) /* the caller doesn't care */ 67 if (requested == 0) /* the caller doesn't care */
67 return nfs_ok; 68 return nfs_ok;
68 if (mode == requested) 69 if (mode == requested) {
70 if (mode == S_IFDIR && !d_can_lookup(dentry)) {
71 WARN_ON_ONCE(1);
72 return nfserr_notdir;
73 }
69 return nfs_ok; 74 return nfs_ok;
75 }
70 /* 76 /*
71 * v4 has an error more specific than err_notdir which we should 77 * v4 has an error more specific than err_notdir which we should
72 * return in preference to err_notdir: 78 * return in preference to err_notdir:
@@ -340,7 +346,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
340 if (error) 346 if (error)
341 goto out; 347 goto out;
342 348
343 error = nfsd_mode_check(rqstp, d_inode(dentry)->i_mode, type); 349 error = nfsd_mode_check(rqstp, dentry, type);
344 if (error) 350 if (error)
345 goto out; 351 goto out;
346 352