]>
Commit | Line | Data |
---|---|---|
47f3b899 SI |
1 | From 3918a0379c7d37ce5d348ec6c2439d744a92a1f8 Mon Sep 17 00:00:00 2001 |
2 | From: "Eric W. Biederman" <ebiederm@xmission.com> | |
3 | Date: Tue, 13 Nov 2018 07:44:37 +0000 | |
4 | Subject: [PATCH 10/11] mount: Retest MNT_LOCKED in do_umount | |
5 | ||
6 | BugLink: https://launchpad.net/bugs/1789161 | |
7 | ||
8 | It was recently pointed out that the one instance of testing MNT_LOCKED | |
9 | outside of the namespace_sem is in ksys_umount. | |
10 | ||
11 | Fix that by adding a test inside of do_umount with namespace_sem and | |
12 | the mount_lock held. As it helps to fail fails the existing test is | |
13 | maintained with an additional comment pointing out that it may be racy | |
14 | because the locks are not held. | |
15 | ||
16 | Cc: stable@vger.kernel.org | |
17 | Reported-by: Al Viro <viro@ZenIV.linux.org.uk> | |
18 | Fixes: 5ff9d8a65ce8 ("vfs: Lock in place mounts from more privileged users") | |
19 | Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> | |
20 | (cherry picked from commit 25d202ed820ee347edec0bf3bf553544556bf64b) | |
21 | Signed-off-by: Tyler Hicks <tyhicks@canonical.com> | |
22 | Acked-by: Colin King <colin.king@canonical.com> | |
23 | Acked-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> | |
24 | Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> | |
25 | --- | |
26 | fs/namespace.c | 10 ++++++++-- | |
27 | 1 file changed, 8 insertions(+), 2 deletions(-) | |
28 | ||
29 | diff --git a/fs/namespace.c b/fs/namespace.c | |
30 | index 570c9672ac9f..dcf107925150 100644 | |
31 | --- a/fs/namespace.c | |
32 | +++ b/fs/namespace.c | |
33 | @@ -1609,8 +1609,13 @@ static int do_umount(struct mount *mnt, int flags) | |
34 | ||
35 | namespace_lock(); | |
36 | lock_mount_hash(); | |
37 | - event++; | |
38 | ||
39 | + /* Recheck MNT_LOCKED with the locks held */ | |
40 | + retval = -EINVAL; | |
41 | + if (mnt->mnt.mnt_flags & MNT_LOCKED) | |
42 | + goto out; | |
43 | + | |
44 | + event++; | |
45 | if (flags & MNT_DETACH) { | |
46 | if (!list_empty(&mnt->mnt_list)) | |
47 | umount_tree(mnt, UMOUNT_PROPAGATE); | |
48 | @@ -1624,6 +1629,7 @@ static int do_umount(struct mount *mnt, int flags) | |
49 | retval = 0; | |
50 | } | |
51 | } | |
52 | +out: | |
53 | unlock_mount_hash(); | |
54 | namespace_unlock(); | |
55 | return retval; | |
56 | @@ -1714,7 +1720,7 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) | |
57 | goto dput_and_out; | |
58 | if (!check_mnt(mnt)) | |
59 | goto dput_and_out; | |
60 | - if (mnt->mnt.mnt_flags & MNT_LOCKED) | |
61 | + if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */ | |
62 | goto dput_and_out; | |
63 | retval = -EPERM; | |
64 | if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN)) | |
65 | -- | |
66 | 2.11.0 | |
67 |