Commit e75b23f9 authored by J. Bruce Fields's avatar J. Bruce Fields

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: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 12391d07
...@@ -59,14 +59,20 @@ static int nfsd_acceptable(void *expv, struct dentry *dentry) ...@@ -59,14 +59,20 @@ static int nfsd_acceptable(void *expv, struct dentry *dentry)
* the write call). * the write call).
*/ */
static inline __be32 static inline __be32
nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, umode_t requested) nfsd_mode_check(struct svc_rqst *rqstp, struct dentry *dentry,
umode_t requested)
{ {
mode &= S_IFMT; umode_t mode = d_inode(dentry)->i_mode & S_IFMT;
if (requested == 0) /* the caller doesn't care */ if (requested == 0) /* the caller doesn't care */
return nfs_ok; return nfs_ok;
if (mode == requested) if (mode == requested) {
if (mode == S_IFDIR && !d_can_lookup(dentry)) {
WARN_ON_ONCE(1);
return nfserr_notdir;
}
return nfs_ok; return nfs_ok;
}
/* /*
* v4 has an error more specific than err_notdir which we should * v4 has an error more specific than err_notdir which we should
* return in preference to err_notdir: * 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,7 +346,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
if (error) if (error)
goto out; goto out;
error = nfsd_mode_check(rqstp, d_inode(dentry)->i_mode, type); error = nfsd_mode_check(rqstp, dentry, type);
if (error) if (error)
goto out; goto out;
......
...@@ -1169,9 +1169,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -1169,9 +1169,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
dentry = fhp->fh_dentry; dentry = fhp->fh_dentry;
dirp = d_inode(dentry); dirp = d_inode(dentry);
err = nfserr_notdir;
if (!dirp->i_op->lookup)
goto out;
/* /*
* Check whether the response file handle has been verified yet. * Check whether the response file handle has been verified yet.
* If it has, the parent directory should already be locked. * If it has, the parent directory should already be locked.
...@@ -1310,12 +1307,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, ...@@ -1310,12 +1307,6 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
dentry = fhp->fh_dentry; dentry = fhp->fh_dentry;
dirp = d_inode(dentry); dirp = d_inode(dentry);
/* Get all the sanity checks out of the way before
* we lock the parent. */
err = nfserr_notdir;
if (!dirp->i_op->lookup)
goto out;
host_err = fh_want_write(fhp); host_err = fh_want_write(fhp);
if (host_err) if (host_err)
goto out_nfserr; goto out_nfserr;
......
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