vfs: make sure we don't have a stale root path if unlazy_walk() fails
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 10 Sep 2013 19:17:49 +0000 (12:17 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 10 Sep 2013 19:17:49 +0000 (12:17 -0700)
When I moved the RCU walk termination into unlazy_walk(), I didn't copy
quite all of it: for the successful RCU termination we properly add the
necessary reference counts to our temporary copy of the root path, but
for the failure case we need to make sure that any temporary root path
information is cleared out (since it does _not_ have the proper
reference counts from the RCU lookup).

We could clean up this mess by just always dropping the temporary root
information, but Al points out that that would mean that a single lookup
through symlinks could see multiple different root entries if it races
with another thread doing chroot.  Not that I think we should really
care (we had that before too, back before we had a copy of the root path
in the nameidata).

Al says he has a cunning plan.  In the meantime, this is the minimal fix
for the problem, even if it's not all that pretty.

Reported-by: Mace Moneta <moneta.mace@gmail.com>
Acked-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/namei.c

index 56e4f4d537d0589912bea3ee629390e894842336..5e6aaadc1dcd994df52a7fcfdc322d0f508cba6f 100644 (file)
@@ -574,9 +574,12 @@ unlock_and_drop_dentry:
 drop_dentry:
        unlock_rcu_walk();
        dput(dentry);
-       return -ECHILD;
+       goto drop_root_mnt;
 out:
        unlock_rcu_walk();
+drop_root_mnt:
+       if (!(nd->flags & LOOKUP_ROOT))
+               nd->root.mnt = NULL;
        return -ECHILD;
 }