Commit 97242f99 authored by Al Viro's avatar Al Viro

link_path_walk(): be careful when failing with ENOTDIR

In RCU mode we might end up with dentry evicted just we check
that it's a directory.  In such case we should return ECHILD
rather than ENOTDIR, so that pathwalk would be retries in non-RCU
mode.

Breakage had been introduced in commit b18825a7 - prior to that
we were looking at nd->inode, which had been fetched before
verifying that ->d_seq was still valid.  That form of check
would only be satisfied if at some point the pathname prefix
would indeed have resolved to a non-directory.  The fix consists
of checking ->d_seq after we'd run into a non-directory dentry,
and failing with ECHILD in case of mismatch.

Note that all branches since 3.12 have that problem...
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent cbfe8fa6
...@@ -1954,9 +1954,14 @@ static int link_path_walk(const char *name, struct nameidata *nd) ...@@ -1954,9 +1954,14 @@ static int link_path_walk(const char *name, struct nameidata *nd)
continue; continue;
} }
} }
if (unlikely(!d_can_lookup(nd->path.dentry))) if (unlikely(!d_can_lookup(nd->path.dentry))) {
if (nd->flags & LOOKUP_RCU) {
if (unlazy_walk(nd, NULL, 0))
return -ECHILD;
}
return -ENOTDIR; return -ENOTDIR;
} }
}
} }
static const char *path_init(struct nameidata *nd, unsigned flags) static const char *path_init(struct nameidata *nd, unsigned flags)
......
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