diff options
author | J. Bruce Fields <bfields@redhat.com> | 2016-07-19 17:33:04 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2016-08-04 17:11:48 -0400 |
commit | e75b23f9e323b1e0759619c39d5a9f7a3a5d9d2c (patch) | |
tree | f87cc0dee5dbb4f22fda8ab3c92dba6e83b75a29 /fs/nfsd/nfsfh.c | |
parent | 12391d07230ec7368269227207b961b2dcb34180 (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.c | 14 |
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 | */ |
61 | static inline __be32 | 61 | static inline __be32 |
62 | nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, umode_t requested) | 62 | nfsd_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 | ||