| @@ -106,6 +106,7 @@ int create_user_ns(struct cred *new) · 105 unmodified lines |
| 106 | 106 | if (!ns) |
| 107 | 107 | goto fail_dec; |
| 108 | 108 | |
| 109 | + ns->parent_could_setfcap = cap_raised(new->cap_effective, CAP_SETFCAP); |
| 109 | 110 | ret = ns_alloc_inum(&ns->ns); |
| 110 | 111 | if (ret) |
| 111 | 112 | goto fail_free; |
| @@ -841,6 +842,60 @@ static int sort_idmaps(struct uid_gid_map *map) · 729 unmodified lines |
| 841 | 842 | return 0; |
| 842 | 843 | } |
| 843 | 844 | |
| 845 | +/** |
| 846 | + * verify_root_map() - check the uid 0 mapping |
| 847 | + * @file: idmapping file |
| 848 | + * @map_ns: user namespace of the target process |
| 849 | + * @new_map: requested idmap |
| 850 | + * |
| 851 | + * If a process requests mapping parent uid 0 into the new ns, verify that the |
| 852 | + * process writing the map had the CAP_SETFCAP capability as the target process |
| 853 | + * will be able to write fscaps that are valid in ancestor user namespaces. |
| 854 | + * |
| 855 | + * Return: true if the mapping is allowed, false if not. |
| 856 | + */ |
| 857 | +static bool verify_root_map(const struct file *file, |
| 858 | + struct user_namespace *map_ns, |
| 859 | + struct uid_gid_map *new_map) |
| 860 | +{ |
| 861 | + int idx; |
| 862 | + const struct user_namespace *file_ns = file->f_cred->user_ns; |
| 863 | + struct uid_gid_extent *extent0 = NULL; |
| 864 | + |
| 865 | + for (idx = 0; idx < new_map->nr_extents; idx++) { |
| 866 | + if (new_map->nr_extents <= UID_GID_MAP_MAX_BASE_EXTENTS) |
| 867 | + extent0 = &new_map->extent[idx]; |
| 868 | + else |
| 869 | + extent0 = &new_map->forward[idx]; |
| 870 | + if (extent0->lower_first == 0) |
| 871 | + break; |
| 872 | + |
| 873 | + extent0 = NULL; |
| 874 | + } |
| 875 | + |
| 876 | + if (!extent0) |
| 877 | + return true; |
| 878 | + |
| 879 | + if (map_ns == file_ns) { |
| 880 | + /* The process unshared its ns and is writing to its own |
| 881 | + * /proc/self/uid_map. User already has full capabilites in |
| 882 | + * the new namespace. Verify that the parent had CAP_SETFCAP |
| 883 | + * when it unshared. |
| 884 | + * */ |
| 885 | + if (!file_ns->parent_could_setfcap) |
| 886 | + return false; |
| 887 | + } else { |
| 888 | + /* Process p1 is writing to uid_map of p2, who is in a child |
| 889 | + * user namespace to p1's. Verify that the opener of the map |
| 890 | + * file has CAP_SETFCAP against the parent of the new map |
| 891 | + * namespace */ |
| 892 | + if (!file_ns_capable(file, map_ns->parent, CAP_SETFCAP)) |
| 893 | + return false; |
| 894 | + } |
| 895 | + |
| 896 | + return true; |
| 897 | +} |
| 898 | + |
| 844 | 899 | static ssize_t map_write(struct file *file, const char __user *buf, |
| 845 | 900 | size_t count, loff_t *ppos, |
| 846 | 901 | int cap_setid, |
| @@ -848,7 +903,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, · 1 unmodified line |
| 848 | 903 | struct uid_gid_map *parent_map) |
| 849 | 904 | { |
| 850 | 905 | struct seq_file *seq = file->private_data; |
| 851 | | − struct user_namespace *ns = seq->private; |
| 906 | + struct user_namespace *map_ns = seq->private; |
| 852 | 907 | struct uid_gid_map new_map; |
| 853 | 908 | unsigned idx; |
| 854 | 909 | struct uid_gid_extent extent; |
| @@ -895,7 +950,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, · 40 unmodified lines |
| 895 | 950 | /* |
| 896 | 951 | * Adjusting namespace settings requires capabilities on the target. |
| 897 | 952 | */ |
| 898 | | − if (cap_valid(cap_setid) && !file_ns_capable(file, ns, CAP_SYS_ADMIN)) |
| 953 | + if (cap_valid(cap_setid) && !file_ns_capable(file, map_ns, CAP_SYS_ADMIN)) |
| 899 | 954 | goto out; |
| 900 | 955 | |
| 901 | 956 | /* Parse the user data */ |
| @@ -965,7 +1020,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, · 63 unmodified lines |
| 965 | 1020 | |
| 966 | 1021 | ret = -EPERM; |
| 967 | 1022 | /* Validate the user is allowed to use user id's mapped to. */ |
| 968 | | − if (!new_idmap_permitted(file, ns, cap_setid, &new_map)) |
| 1023 | + if (!new_idmap_permitted(file, map_ns, cap_setid, &new_map)) |
| 969 | 1024 | goto out; |
| 970 | 1025 | |
| 971 | 1026 | ret = -EPERM; |
| @@ -1086,6 +1141,10 @@ static bool new_idmap_permitted(const struct file *file, · 114 unmodified lines |
| 1086 | 1141 | struct uid_gid_map *new_map) |
| 1087 | 1142 | { |
| 1088 | 1143 | const struct cred *cred = file->f_cred; |
| 1144 | + |
| 1145 | + if (cap_setid == CAP_SETUID && !verify_root_map(file, ns, new_map)) |
| 1146 | + return false; |
| 1147 | + |
| 1089 | 1148 | /* Don't allow mappings that would allow anything that wouldn't |
| 1090 | 1149 | * be allowed without the establishment of unprivileged mappings. |
| 1091 | 1150 | */ |