Message ID | 20240204021739.1157830-2-viro@zeniv.linux.org.uk (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [01/13] fs/super.c: don't drop ->s_user_ns until we free struct super_block itself | expand |
On Sun, Feb 04, 2024 at 02:17:28AM +0000, Al Viro wrote: > If lazy call of ->permission() returns a hard error, check that > try_to_unlazy() succeeds before returning it. That both makes > life easier for ->permission() instances and closes the race > in ENOTDIR handling - it is possible that positive d_can_lookup() > seen in link_path_walk() applies to the state *after* unlink() + > mkdir(), while nd->inode matches the state prior to that. > > Normally seeing e.g. EACCES from permission check in rcu pathwalk > means that with some timings non-rcu pathwalk would've run into > the same; however, running into a non-executable regular file > in the middle of a pathname would not get to permission check - > it would fail with ENOTDIR instead. > > Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> > --- Reviewed-by: Christian Brauner <brauner@kernel.org>
diff --git a/fs/namei.c b/fs/namei.c index 4e0de939fea1..9342fa6a38c2 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1717,7 +1717,11 @@ static inline int may_lookup(struct mnt_idmap *idmap, { if (nd->flags & LOOKUP_RCU) { int err = inode_permission(idmap, nd->inode, MAY_EXEC|MAY_NOT_BLOCK); - if (err != -ECHILD || !try_to_unlazy(nd)) + if (!err) // success, keep going + return 0; + if (!try_to_unlazy(nd)) + return -ECHILD; // redo it all non-lazy + if (err != -ECHILD) // hard error return err; } return inode_permission(idmap, nd->inode, MAY_EXEC);
If lazy call of ->permission() returns a hard error, check that try_to_unlazy() succeeds before returning it. That both makes life easier for ->permission() instances and closes the race in ENOTDIR handling - it is possible that positive d_can_lookup() seen in link_path_walk() applies to the state *after* unlink() + mkdir(), while nd->inode matches the state prior to that. Normally seeing e.g. EACCES from permission check in rcu pathwalk means that with some timings non-rcu pathwalk would've run into the same; however, running into a non-executable regular file in the middle of a pathname would not get to permission check - it would fail with ENOTDIR instead. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> --- fs/namei.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)