From d9d0c09e0a3b7515108dbd1c96f85c776aefd0e1 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 8 May 2021 13:12:03 +0200 Subject: [PATCH] Revert "capabilities: require CAP_SETFCAP to map uid 0" This reverts commit fb4c1c2e9fd1adb19452bbaa75f0f2bb2826ac0d. Fixes the ABI issues in 5.10.35 that at the moment, we can't handle due to the KABI freeze. These are not patches that mean much for android systems, and will be reverted the next KABI "reset" point. Bug: 161946584 Signed-off-by: Greg Kroah-Hartman Change-Id: I7b12040440bc2bedfbabc71d60339cb843e59570 --- include/linux/user_namespace.h | 3 -- include/uapi/linux/capability.h | 3 +- kernel/user_namespace.c | 65 ++------------------------------- 3 files changed, 4 insertions(+), 67 deletions(-) diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 71cc05ddaa21..2330b911ee47 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -65,9 +65,6 @@ struct user_namespace { kgid_t group; struct ns_common ns; unsigned long flags; - /* parent_could_setfcap: true if the creator if this ns had CAP_SETFCAP - * in its effective capability set at the child ns creation time. */ - bool parent_could_setfcap; #ifdef CONFIG_KEYS /* List of joinable keyrings in this namespace. Modification access of diff --git a/include/uapi/linux/capability.h b/include/uapi/linux/capability.h index 741985d12f7d..395dd0df8d08 100644 --- a/include/uapi/linux/capability.h +++ b/include/uapi/linux/capability.h @@ -333,8 +333,7 @@ struct vfs_ns_cap_data { #define CAP_AUDIT_CONTROL 30 -/* Set or remove capabilities on files. - Map uid=0 into a child user namespace. */ +/* Set or remove capabilities on files */ #define CAP_SETFCAP 31 diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index ce396ea4de60..e703d5d9cbe8 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -106,7 +106,6 @@ int create_user_ns(struct cred *new) if (!ns) goto fail_dec; - ns->parent_could_setfcap = cap_raised(new->cap_effective, CAP_SETFCAP); ret = ns_alloc_inum(&ns->ns); if (ret) goto fail_free; @@ -842,60 +841,6 @@ static int sort_idmaps(struct uid_gid_map *map) return 0; } -/** - * verify_root_map() - check the uid 0 mapping - * @file: idmapping file - * @map_ns: user namespace of the target process - * @new_map: requested idmap - * - * If a process requests mapping parent uid 0 into the new ns, verify that the - * process writing the map had the CAP_SETFCAP capability as the target process - * will be able to write fscaps that are valid in ancestor user namespaces. - * - * Return: true if the mapping is allowed, false if not. - */ -static bool verify_root_map(const struct file *file, - struct user_namespace *map_ns, - struct uid_gid_map *new_map) -{ - int idx; - const struct user_namespace *file_ns = file->f_cred->user_ns; - struct uid_gid_extent *extent0 = NULL; - - for (idx = 0; idx < new_map->nr_extents; idx++) { - if (new_map->nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) - extent0 = &new_map->extent[idx]; - else - extent0 = &new_map->forward[idx]; - if (extent0->lower_first == 0) - break; - - extent0 = NULL; - } - - if (!extent0) - return true; - - if (map_ns == file_ns) { - /* The process unshared its ns and is writing to its own - * /proc/self/uid_map. User already has full capabilites in - * the new namespace. Verify that the parent had CAP_SETFCAP - * when it unshared. - * */ - if (!file_ns->parent_could_setfcap) - return false; - } else { - /* Process p1 is writing to uid_map of p2, who is in a child - * user namespace to p1's. Verify that the opener of the map - * file has CAP_SETFCAP against the parent of the new map - * namespace */ - if (!file_ns_capable(file, map_ns->parent, CAP_SETFCAP)) - return false; - } - - return true; -} - static ssize_t map_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos, int cap_setid, @@ -903,7 +848,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, struct uid_gid_map *parent_map) { struct seq_file *seq = file->private_data; - struct user_namespace *map_ns = seq->private; + struct user_namespace *ns = seq->private; struct uid_gid_map new_map; unsigned idx; struct uid_gid_extent extent; @@ -950,7 +895,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, /* * Adjusting namespace settings requires capabilities on the target. */ - if (cap_valid(cap_setid) && !file_ns_capable(file, map_ns, CAP_SYS_ADMIN)) + if (cap_valid(cap_setid) && !file_ns_capable(file, ns, CAP_SYS_ADMIN)) goto out; /* Parse the user data */ @@ -1020,7 +965,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, ret = -EPERM; /* Validate the user is allowed to use user id's mapped to. */ - if (!new_idmap_permitted(file, map_ns, cap_setid, &new_map)) + if (!new_idmap_permitted(file, ns, cap_setid, &new_map)) goto out; ret = -EPERM; @@ -1141,10 +1086,6 @@ static bool new_idmap_permitted(const struct file *file, struct uid_gid_map *new_map) { const struct cred *cred = file->f_cred; - - if (cap_setid == CAP_SETUID && !verify_root_map(file, ns, new_map)) - return false; - /* Don't allow mappings that would allow anything that wouldn't * be allowed without the establishment of unprivileged mappings. */