]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.19.7/rcu-pathwalk-breakage-when-running-into-a-symlink-overmounting-something.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.19.7 / rcu-pathwalk-breakage-when-running-into-a-symlink-overmounting-something.patch
1 From 3cab989afd8d8d1bc3d99fef0e7ed87c31e7b647 Mon Sep 17 00:00:00 2001
2 From: Al Viro <viro@zeniv.linux.org.uk>
3 Date: Fri, 24 Apr 2015 15:47:07 -0400
4 Subject: RCU pathwalk breakage when running into a symlink overmounting something
5
6 From: Al Viro <viro@zeniv.linux.org.uk>
7
8 commit 3cab989afd8d8d1bc3d99fef0e7ed87c31e7b647 upstream.
9
10 Calling unlazy_walk() in walk_component() and do_last() when we find
11 a symlink that needs to be followed doesn't acquire a reference to vfsmount.
12 That's fine when the symlink is on the same vfsmount as the parent directory
13 (which is almost always the case), but it's not always true - one _can_
14 manage to bind a symlink on top of something. And in such cases we end up
15 with excessive mntput().
16
17 Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
18 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
19
20 ---
21 fs/namei.c | 6 ++++--
22 1 file changed, 4 insertions(+), 2 deletions(-)
23
24 --- a/fs/namei.c
25 +++ b/fs/namei.c
26 @@ -1585,7 +1585,8 @@ static inline int walk_component(struct
27
28 if (should_follow_link(path->dentry, follow)) {
29 if (nd->flags & LOOKUP_RCU) {
30 - if (unlikely(unlazy_walk(nd, path->dentry))) {
31 + if (unlikely(nd->path.mnt != path->mnt ||
32 + unlazy_walk(nd, path->dentry))) {
33 err = -ECHILD;
34 goto out_err;
35 }
36 @@ -3028,7 +3029,8 @@ finish_lookup:
37
38 if (should_follow_link(path->dentry, !symlink_ok)) {
39 if (nd->flags & LOOKUP_RCU) {
40 - if (unlikely(unlazy_walk(nd, path->dentry))) {
41 + if (unlikely(nd->path.mnt != path->mnt ||
42 + unlazy_walk(nd, path->dentry))) {
43 error = -ECHILD;
44 goto out;
45 }