Skip to content

Commit d2f007d

Browse files
thejhebiederm
authored andcommitted
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: 6397fac ("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>
1 parent 6510223 commit d2f007d

File tree

1 file changed

+8
-4
lines changed

1 file changed

+8
-4
lines changed

kernel/user_namespace.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -974,10 +974,6 @@ static ssize_t map_write(struct file *file, const char __user *buf,
974974
if (!new_idmap_permitted(file, ns, cap_setid, &new_map))
975975
goto out;
976976

977-
ret = sort_idmaps(&new_map);
978-
if (ret < 0)
979-
goto out;
980-
981977
ret = -EPERM;
982978
/* Map the lower ids from the parent user namespace to the
983979
* kernel global id space.
@@ -1004,6 +1000,14 @@ static ssize_t map_write(struct file *file, const char __user *buf,
10041000
e->lower_first = lower_first;
10051001
}
10061002

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+
10071011
/* Install the map */
10081012
if (new_map.nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) {
10091013
memcpy(map->extent, new_map.extent,

0 commit comments

Comments
 (0)