]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
vfs: fix race in rcu lookup of pruned dentry
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 26 Jul 2011 20:04:16 +0000 (13:04 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 3 Aug 2011 19:42:48 +0000 (12:42 -0700)
Backport of commit 59430262401bec02d415179c43dbe5b8819c09ce
done by Hugh Dickins <hughd@google.com>

Don't update *inode in __follow_mount_rcu() until we'd verified that
there is mountpoint there.  Kudos to Hugh Dickins for catching that
one in the first place and eventually figuring out the solution (and
catching a braino in the earlier version of patch).

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/namei.c

index 6ff858c049c030fd5ea1e142a02c39bb4b51a2dc..732a754d536e33d4bc5845557ad458c6d2b9c0fe 100644 (file)
@@ -1013,7 +1013,6 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
                 * Don't forget we might have a non-mountpoint managed dentry
                 * that wants to block transit.
                 */
-               *inode = path->dentry->d_inode;
                if (!reverse_transit &&
                     unlikely(managed_dentry_might_block(path->dentry)))
                        return false;
@@ -1027,6 +1026,12 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
                path->mnt = mounted;
                path->dentry = mounted->mnt_root;
                nd->seq = read_seqcount_begin(&path->dentry->d_seq);
+               /*
+                * Update the inode too. We don't need to re-check the
+                * dentry sequence number here after this d_inode read,
+                * because a mount-point is always pinned.
+                */
+               *inode = path->dentry->d_inode;
        }
 
        if (unlikely(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT))