|
@@ -59,14 +59,20 @@ static int nfsd_acceptable(void *expv, struct dentry *dentry)
|
|
|
* the write call).
|
|
|
*/
|
|
|
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 */
|
|
|
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;
|
|
|
+ }
|
|
|
/*
|
|
|
* v4 has an error more specific than err_notdir which we should
|
|
|
* 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)
|
|
|
if (error)
|
|
|
goto out;
|
|
|
|
|
|
- error = nfsd_mode_check(rqstp, d_inode(dentry)->i_mode, type);
|
|
|
+ error = nfsd_mode_check(rqstp, dentry, type);
|
|
|
if (error)
|
|
|
goto out;
|
|
|
|