Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Inline map creation logic in map_create() function

Currently find_and_alloc_map() performs two separate functions: some
argument sanity checking and partial map creation workflow hanling.
Neither of those functions are self-sufficient and are augmented by
further checks and initialization logic in the caller (map_create()
function). So unify all the sanity checks, permission checks, and
creation and initialization logic in one linear piece of code in
map_create() instead. This also make it easier to further enhance
permission checks and keep them located in one place.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Stanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/bpf/20230613223533.3689589-3-andrii@kernel.org

authored by

Andrii Nakryiko and committed by
Daniel Borkmann
22db4122 1d28635a

+24 -33
+24 -33
kernel/bpf/syscall.c
··· 109 109 .map_mem_usage = bpf_map_offload_map_mem_usage, 110 110 }; 111 111 112 - static struct bpf_map *find_and_alloc_map(union bpf_attr *attr) 113 - { 114 - const struct bpf_map_ops *ops; 115 - u32 type = attr->map_type; 116 - struct bpf_map *map; 117 - int err; 118 - 119 - if (type >= ARRAY_SIZE(bpf_map_types)) 120 - return ERR_PTR(-EINVAL); 121 - type = array_index_nospec(type, ARRAY_SIZE(bpf_map_types)); 122 - ops = bpf_map_types[type]; 123 - if (!ops) 124 - return ERR_PTR(-EINVAL); 125 - 126 - if (ops->map_alloc_check) { 127 - err = ops->map_alloc_check(attr); 128 - if (err) 129 - return ERR_PTR(err); 130 - } 131 - if (attr->map_ifindex) 132 - ops = &bpf_map_offload_ops; 133 - if (!ops->map_mem_usage) 134 - return ERR_PTR(-EINVAL); 135 - map = ops->map_alloc(attr); 136 - if (IS_ERR(map)) 137 - return map; 138 - map->ops = ops; 139 - map->map_type = type; 140 - return map; 141 - } 142 - 143 112 static void bpf_map_write_active_inc(struct bpf_map *map) 144 113 { 145 114 atomic64_inc(&map->writecnt); ··· 1096 1127 /* called via syscall */ 1097 1128 static int map_create(union bpf_attr *attr) 1098 1129 { 1130 + const struct bpf_map_ops *ops; 1099 1131 int numa_node = bpf_map_attr_numa_node(attr); 1132 + u32 map_type = attr->map_type; 1100 1133 struct bpf_map *map; 1101 1134 int f_flags; 1102 1135 int err; ··· 1128 1157 !node_online(numa_node))) 1129 1158 return -EINVAL; 1130 1159 1160 + /* find map type and init map: hashtable vs rbtree vs bloom vs ... */ 1161 + map_type = attr->map_type; 1162 + if (map_type >= ARRAY_SIZE(bpf_map_types)) 1163 + return -EINVAL; 1164 + map_type = array_index_nospec(map_type, ARRAY_SIZE(bpf_map_types)); 1165 + ops = bpf_map_types[map_type]; 1166 + if (!ops) 1167 + return -EINVAL; 1168 + 1169 + if (ops->map_alloc_check) { 1170 + err = ops->map_alloc_check(attr); 1171 + if (err) 1172 + return err; 1173 + } 1174 + if (attr->map_ifindex) 1175 + ops = &bpf_map_offload_ops; 1176 + if (!ops->map_mem_usage) 1177 + return -EINVAL; 1178 + 1131 1179 /* Intent here is for unprivileged_bpf_disabled to block BPF map 1132 1180 * creation for unprivileged users; other actions depend 1133 1181 * on fd availability and access to bpffs, so are dependent on ··· 1156 1166 if (sysctl_unprivileged_bpf_disabled && !bpf_capable()) 1157 1167 return -EPERM; 1158 1168 1159 - /* find map type and init map: hashtable vs rbtree vs bloom vs ... */ 1160 - map = find_and_alloc_map(attr); 1169 + map = ops->map_alloc(attr); 1161 1170 if (IS_ERR(map)) 1162 1171 return PTR_ERR(map); 1172 + map->ops = ops; 1173 + map->map_type = map_type; 1163 1174 1164 1175 err = bpf_obj_name_cpy(map->name, attr->map_name, 1165 1176 sizeof(attr->map_name));