aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJann Horn <jannh@google.com>2018-11-05 14:55:09 -0500
committerEric W. Biederman <ebiederm@xmission.com>2018-11-08 00:51:16 -0500
commitd2f007dbe7e4c9583eea6eb04d60001e85c6f1bd (patch)
tree9720c07318f1c5591dd3fb67a9bfdc80efc1f2da /kernel
parent651022382c7f8da46cb4872a545ee1da6d097d2a (diff)
userns: also map extents in the reverse map to kernel IDs
The current logic first clones the extent array and sorts both copies, then maps the lower IDs of the forward mapping into the lower namespace, but doesn't map the lower IDs of the reverse mapping. This means that code in a nested user namespace with >5 extents will see incorrect IDs. It also breaks some access checks, like inode_owner_or_capable() and privileged_wrt_inode_uidgid(), so a process can incorrectly appear to be capable relative to an inode. To fix it, we have to make sure that the "lower_first" members of extents in both arrays are translated; and we have to make sure that the reverse map is sorted *after* the translation (since otherwise the translation can break the sorting). This is CVE-2018-18955. Fixes: 6397fac4915a ("userns: bump idmap limits to 340") Cc: stable@vger.kernel.org Signed-off-by: Jann Horn <jannh@google.com> Tested-by: Eric W. Biederman <ebiederm@xmission.com> Reviewed-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/user_namespace.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index e5222b5fb4fe..923414a246e9 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -974,10 +974,6 @@ static ssize_t map_write(struct file *file, const char __user *buf,
974 if (!new_idmap_permitted(file, ns, cap_setid, &new_map)) 974 if (!new_idmap_permitted(file, ns, cap_setid, &new_map))
975 goto out; 975 goto out;
976 976
977 ret = sort_idmaps(&new_map);
978 if (ret < 0)
979 goto out;
980
981 ret = -EPERM; 977 ret = -EPERM;
982 /* Map the lower ids from the parent user namespace to the 978 /* Map the lower ids from the parent user namespace to the
983 * kernel global id space. 979 * kernel global id space.
@@ -1004,6 +1000,14 @@ static ssize_t map_write(struct file *file, const char __user *buf,
1004 e->lower_first = lower_first; 1000 e->lower_first = lower_first;
1005 } 1001 }
1006 1002
1003 /*
1004 * If we want to use binary search for lookup, this clones the extent
1005 * array and sorts both copies.
1006 */
1007 ret = sort_idmaps(&new_map);
1008 if (ret < 0)
1009 goto out;
1010
1007 /* Install the map */ 1011 /* Install the map */
1008 if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) { 1012 if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) {
1009 memcpy(map->extent, new_map.extent, 1013 memcpy(map->extent, new_map.extent,