History

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.

Andrii Nakryiko committed 3 years ago

Commit 22db4121 parent 1d286351 file · +24 −33Browse files

Unified · Split

kernel/bpf/syscall.c+24−33
@@ -109,37 +109,6 @@ const struct bpf_map_ops bpf_map_offload_ops = { · 108 unmodified lines
109109 .map_mem_usage = bpf_map_offload_map_mem_usage,
110110 };
111111
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−
143112 static void bpf_map_write_active_inc(struct bpf_map *map)
144113 {
145114 atomic64_inc(&map->writecnt);
@@ -1127,7 +1096,9 @@ free_map_tab: · 981 unmodified lines
11271096 /* called via syscall */
11281097 static int map_create(union bpf_attr *attr)
11291098 {
1099+ const struct bpf_map_ops *ops;
11301100 int numa_node = bpf_map_attr_numa_node(attr);
1101+ u32 map_type = attr->map_type;
11311102 struct bpf_map *map;
11321103 int f_flags;
11331104 int err;
@@ -1157,6 +1128,25 @@ static int map_create(union bpf_attr *attr) · 23 unmodified lines
11571128 !node_online(numa_node)))
11581129 return -EINVAL;
11591130
1131+ /* find map type and init map: hashtable vs rbtree vs bloom vs ... */
1132+ map_type = attr->map_type;
1133+ if (map_type >= ARRAY_SIZE(bpf_map_types))
1134+ return -EINVAL;
1135+ map_type = array_index_nospec(map_type, ARRAY_SIZE(bpf_map_types));
1136+ ops = bpf_map_types[map_type];
1137+ if (!ops)
1138+ return -EINVAL;
1139+
1140+ if (ops->map_alloc_check) {
1141+ err = ops->map_alloc_check(attr);
1142+ if (err)
1143+ return err;
1144+ }
1145+ if (attr->map_ifindex)
1146+ ops = &bpf_map_offload_ops;
1147+ if (!ops->map_mem_usage)
1148+ return -EINVAL;
1149+
11601150 /* Intent here is for unprivileged_bpf_disabled to block BPF map
11611151 * creation for unprivileged users; other actions depend
11621152 * on fd availability and access to bpffs, so are dependent on
@@ -1166,10 +1156,11 @@ static int map_create(union bpf_attr *attr) · 3 unmodified lines
11661156 if (sysctl_unprivileged_bpf_disabled && !bpf_capable())
11671157 return -EPERM;
11681158
1169− /* find map type and init map: hashtable vs rbtree vs bloom vs ... */
1170− map = find_and_alloc_map(attr);
1159+ map = ops->map_alloc(attr);
11711160 if (IS_ERR(map))
11721161 return PTR_ERR(map);
1162+ map->ops = ops;
1163+ map->map_type = map_type;
11731164
11741165 err = bpf_obj_name_cpy(map->name, attr->map_name,
11751166 sizeof(attr->map_name));