diff --git a/fs/namei.c b/fs/namei.c index bf0f66f0e9b9..87c99149a152 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1896,6 +1896,14 @@ static inline int may_lookup(struct mnt_idmap *idmap, { int err, mask; + struct dentry *_dentry = nd->path.dentry; + struct inode *_inode = READ_ONCE(_dentry->d_inode); + if (!d_can_lookup(_dentry) || !_inode || !S_ISDIR(_inode->i_mode)) { + spin_lock(&_dentry->d_lock); + VFS_BUG_ON_INODE(d_can_lookup(_dentry) && !S_ISDIR(_dentry->d_inode->i_mode), _dentry->d_inode); + spin_unlock(&_dentry->d_lock); + } + mask = nd->flags & LOOKUP_RCU ? MAY_NOT_BLOCK : 0; err = lookup_inode_permission_may_exec(idmap, nd->inode, mask); if (likely(!err)) @@ -2527,6 +2535,14 @@ static int link_path_walk(const char *name, struct nameidata *nd) return 0; } + struct dentry *_dentry = nd->path.dentry; + struct inode *_inode = READ_ONCE(_dentry->d_inode); + if (!d_can_lookup(_dentry) || !_inode || !S_ISDIR(_inode->i_mode)) { + spin_lock(&_dentry->d_lock); + VFS_BUG_ON_INODE(d_can_lookup(_dentry) && !S_ISDIR(_dentry->d_inode->i_mode), _dentry->d_inode); + spin_unlock(&_dentry->d_lock); + } + /* At this point we know we have a real path component. */ for(;;) { struct mnt_idmap *idmap;