]>
Commit | Line | Data |
---|---|---|
47f3b899 SI |
1 | From 5506202b83e65b844309093e712b5b507eb1e403 Mon Sep 17 00:00:00 2001 |
2 | From: Jann Horn <jannh@google.com> | |
3 | Date: Tue, 13 Nov 2018 07:42:38 +0000 | |
4 | Subject: [PATCH 09/11] userns: also map extents in the reverse map to kernel | |
5 | IDs | |
6 | ||
7 | BugLink: https://launchpad.net/bugs/1801924 | |
8 | ||
9 | The current logic first clones the extent array and sorts both copies, then | |
10 | maps the lower IDs of the forward mapping into the lower namespace, but | |
11 | doesn't map the lower IDs of the reverse mapping. | |
12 | ||
13 | This means that code in a nested user namespace with >5 extents will see | |
14 | incorrect IDs. It also breaks some access checks, like | |
15 | inode_owner_or_capable() and privileged_wrt_inode_uidgid(), so a process | |
16 | can incorrectly appear to be capable relative to an inode. | |
17 | ||
18 | To fix it, we have to make sure that the "lower_first" members of extents | |
19 | in both arrays are translated; and we have to make sure that the reverse | |
20 | map is sorted *after* the translation (since otherwise the translation can | |
21 | break the sorting). | |
22 | ||
23 | This is CVE-2018-18955. | |
24 | ||
25 | Fixes: 6397fac4915a ("userns: bump idmap limits to 340") | |
26 | Cc: stable@vger.kernel.org | |
27 | Signed-off-by: Jann Horn <jannh@google.com> | |
28 | Tested-by: Eric W. Biederman <ebiederm@xmission.com> | |
29 | Reviewed-by: Eric W. Biederman <ebiederm@xmission.com> | |
30 | Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> | |
31 | ||
32 | CVE-2018-18955 | |
33 | ||
34 | (cherry picked from commit d2f007dbe7e4c9583eea6eb04d60001e85c6f1bd) | |
35 | Signed-off-by: Tyler Hicks <tyhicks@canonical.com> | |
36 | Acked-by: Colin King <colin.king@canonical.com> | |
37 | Acked-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> | |
38 | Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com> | |
39 | --- | |
40 | kernel/user_namespace.c | 12 ++++++++---- | |
41 | 1 file changed, 8 insertions(+), 4 deletions(-) | |
42 | ||
43 | diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c | |
44 | index 08d638386b83..12de8c144db9 100644 | |
45 | --- a/kernel/user_namespace.c | |
46 | +++ b/kernel/user_namespace.c | |
47 | @@ -983,10 +983,6 @@ static ssize_t map_write(struct file *file, const char __user *buf, | |
48 | if (!new_idmap_permitted(file, ns, cap_setid, &new_map)) | |
49 | goto out; | |
50 | ||
51 | - ret = sort_idmaps(&new_map); | |
52 | - if (ret < 0) | |
53 | - goto out; | |
54 | - | |
55 | ret = -EPERM; | |
56 | /* Map the lower ids from the parent user namespace to the | |
57 | * kernel global id space. | |
58 | @@ -1013,6 +1009,14 @@ static ssize_t map_write(struct file *file, const char __user *buf, | |
59 | e->lower_first = lower_first; | |
60 | } | |
61 | ||
62 | + /* | |
63 | + * If we want to use binary search for lookup, this clones the extent | |
64 | + * array and sorts both copies. | |
65 | + */ | |
66 | + ret = sort_idmaps(&new_map); | |
67 | + if (ret < 0) | |
68 | + goto out; | |
69 | + | |
70 | /* Install the map */ | |
71 | if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) { | |
72 | memcpy(map->extent, new_map.extent, | |
73 | -- | |
74 | 2.11.0 | |
75 |