| @@ -106,6 +106,7 @@ int create_user_ns(struct cred *new) · 105 unmodified lines |
| 106 | if (!ns) | 106 | if (!ns) |
| 107 | goto fail_dec; | 107 | goto fail_dec; |
| 108 | | 108 | |
| | 109 | ns->parent_could_setfcap = cap_raised(new->cap_effective, CAP_SETFCAP); |
| 109 | ret = ns_alloc_inum(&ns->ns); | 110 | ret = ns_alloc_inum(&ns->ns); |
| 110 | if (ret) | 111 | if (ret) |
| 111 | goto fail_free; | 112 | goto fail_free; |
| @@ -841,6 +842,60 @@ static int sort_idmaps(struct uid_gid_map *map) · 729 unmodified lines |
| 841 | return 0; | 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 | static ssize_t map_write(struct file *file, const char __user *buf, | 899 | static ssize_t map_write(struct file *file, const char __user *buf, |
| 845 | size_t count, loff_t *ppos, | 900 | size_t count, loff_t *ppos, |
| 846 | int cap_setid, | 901 | int cap_setid, |
| @@ -848,7 +903,7 @@ static ssize_t map_write(struct file *file, const char __user *buf, · 1 unmodified line |
| 848 | struct uid_gid_map *parent_map) | 903 | struct uid_gid_map *parent_map) |
| 849 | { | 904 | { |
| 850 | struct seq_file *seq = file->private_data; | 905 | struct seq_file *seq = file->private_data; |
| 851 | struct user_namespace *ns = seq->private; | 906 | struct user_namespace *map_ns = seq->private; |
| 852 | struct uid_gid_map new_map; | 907 | struct uid_gid_map new_map; |
| 853 | unsigned idx; | 908 | unsigned idx; |
| 854 | struct uid_gid_extent extent; | 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 | * Adjusting namespace settings requires capabilities on the target. | 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 | goto out; | 954 | goto out; |
| 900 | | 955 | |
| 901 | /* Parse the user data */ | 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 | ret = -EPERM; | 1021 | ret = -EPERM; |
| 967 | /* Validate the user is allowed to use user id's mapped to. */ | 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 | goto out; | 1024 | goto out; |
| 970 | | 1025 | |
| 971 | ret = -EPERM; | 1026 | ret = -EPERM; |
| @@ -1086,6 +1141,10 @@ static bool new_idmap_permitted(const struct file *file, · 114 unmodified lines |
| 1086 | struct uid_gid_map *new_map) | 1141 | struct uid_gid_map *new_map) |
| 1087 | { | 1142 | { |
| 1088 | const struct cred *cred = file->f_cred; | 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 | /* Don't allow mappings that would allow anything that wouldn't | 1148 | /* Don't allow mappings that would allow anything that wouldn't |
| 1090 | * be allowed without the establishment of unprivileged mappings. | 1149 | * be allowed without the establishment of unprivileged mappings. |
| 1091 | */ | 1150 | */ |