]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - kernel/bpf/arraymap.c
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-jammy-kernel.git] / kernel / bpf / arraymap.c
CommitLineData
5b497af4 1// SPDX-License-Identifier: GPL-2.0-only
28fbcfa0 2/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
81ed18ab 3 * Copyright (c) 2016,2017 Facebook
28fbcfa0
AS
4 */
5#include <linux/bpf.h>
a26ca7c9 6#include <linux/btf.h>
28fbcfa0 7#include <linux/err.h>
28fbcfa0
AS
8#include <linux/slab.h>
9#include <linux/mm.h>
04fd61ab 10#include <linux/filter.h>
0cdf5640 11#include <linux/perf_event.h>
a26ca7c9 12#include <uapi/linux/btf.h>
28fbcfa0 13
56f668df
MKL
14#include "map_in_map.h"
15
6e71b04a 16#define ARRAY_CREATE_FLAG_MASK \
591fe988 17 (BPF_F_NUMA_NODE | BPF_F_ACCESS_MASK)
6e71b04a 18
a10423b8
AS
19static void bpf_array_free_percpu(struct bpf_array *array)
20{
21 int i;
22
32fff239 23 for (i = 0; i < array->map.max_entries; i++) {
a10423b8 24 free_percpu(array->pptrs[i]);
32fff239
ED
25 cond_resched();
26 }
a10423b8
AS
27}
28
29static int bpf_array_alloc_percpu(struct bpf_array *array)
30{
31 void __percpu *ptr;
32 int i;
33
34 for (i = 0; i < array->map.max_entries; i++) {
35 ptr = __alloc_percpu_gfp(array->elem_size, 8,
36 GFP_USER | __GFP_NOWARN);
37 if (!ptr) {
38 bpf_array_free_percpu(array);
39 return -ENOMEM;
40 }
41 array->pptrs[i] = ptr;
32fff239 42 cond_resched();
a10423b8
AS
43 }
44
45 return 0;
46}
47
28fbcfa0 48/* Called from syscall */
5dc4c4b7 49int array_map_alloc_check(union bpf_attr *attr)
28fbcfa0 50{
a10423b8 51 bool percpu = attr->map_type == BPF_MAP_TYPE_PERCPU_ARRAY;
96eabe7a 52 int numa_node = bpf_map_attr_numa_node(attr);
28fbcfa0
AS
53
54 /* check sanity of attributes */
55 if (attr->max_entries == 0 || attr->key_size != 4 ||
6e71b04a
CF
56 attr->value_size == 0 ||
57 attr->map_flags & ~ARRAY_CREATE_FLAG_MASK ||
591fe988 58 !bpf_map_flags_access_ok(attr->map_flags) ||
96eabe7a 59 (percpu && numa_node != NUMA_NO_NODE))
ad46061f 60 return -EINVAL;
28fbcfa0 61
7984c27c 62 if (attr->value_size > KMALLOC_MAX_SIZE)
01b3f521
AS
63 /* if value_size is bigger, the user space won't be able to
64 * access the elements.
65 */
ad46061f
JK
66 return -E2BIG;
67
68 return 0;
69}
70
71static struct bpf_map *array_map_alloc(union bpf_attr *attr)
72{
73 bool percpu = attr->map_type == BPF_MAP_TYPE_PERCPU_ARRAY;
9c2d63b8 74 int ret, numa_node = bpf_map_attr_numa_node(attr);
ad46061f
JK
75 u32 elem_size, index_mask, max_entries;
76 bool unpriv = !capable(CAP_SYS_ADMIN);
9c2d63b8 77 u64 cost, array_size, mask64;
ad46061f 78 struct bpf_array *array;
01b3f521 79
28fbcfa0
AS
80 elem_size = round_up(attr->value_size, 8);
81
b2157399 82 max_entries = attr->max_entries;
b2157399 83
bbeb6e43
DB
84 /* On 32 bit archs roundup_pow_of_two() with max_entries that has
85 * upper most bit set in u32 space is undefined behavior due to
86 * resulting 1U << 32, so do it manually here in u64 space.
87 */
88 mask64 = fls_long(max_entries - 1);
89 mask64 = 1ULL << mask64;
90 mask64 -= 1;
91
92 index_mask = mask64;
93 if (unpriv) {
b2157399
AS
94 /* round up array size to nearest power of 2,
95 * since cpu will speculate within index_mask limits
96 */
97 max_entries = index_mask + 1;
bbeb6e43
DB
98 /* Check for overflows. */
99 if (max_entries < attr->max_entries)
100 return ERR_PTR(-E2BIG);
101 }
b2157399 102
a10423b8
AS
103 array_size = sizeof(*array);
104 if (percpu)
b2157399 105 array_size += (u64) max_entries * sizeof(void *);
a10423b8 106 else
b2157399 107 array_size += (u64) max_entries * elem_size;
a10423b8
AS
108
109 /* make sure there is no u32 overflow later in round_up() */
9c2d63b8
DB
110 cost = array_size;
111 if (cost >= U32_MAX - PAGE_SIZE)
daaf427c 112 return ERR_PTR(-ENOMEM);
9c2d63b8
DB
113 if (percpu) {
114 cost += (u64)attr->max_entries * elem_size * num_possible_cpus();
115 if (cost >= U32_MAX - PAGE_SIZE)
116 return ERR_PTR(-ENOMEM);
117 }
118 cost = round_up(cost, PAGE_SIZE) >> PAGE_SHIFT;
119
120 ret = bpf_map_precharge_memlock(cost);
121 if (ret < 0)
122 return ERR_PTR(ret);
daaf427c 123
28fbcfa0 124 /* allocate all map elements and zero-initialize them */
96eabe7a 125 array = bpf_map_area_alloc(array_size, numa_node);
d407bd25
DB
126 if (!array)
127 return ERR_PTR(-ENOMEM);
b2157399
AS
128 array->index_mask = index_mask;
129 array->map.unpriv_array = unpriv;
28fbcfa0
AS
130
131 /* copy mandatory map attributes */
32852649 132 bpf_map_init_from_attr(&array->map, attr);
9c2d63b8 133 array->map.pages = cost;
28fbcfa0
AS
134 array->elem_size = elem_size;
135
9c2d63b8 136 if (percpu && bpf_array_alloc_percpu(array)) {
d407bd25 137 bpf_map_area_free(array);
a10423b8
AS
138 return ERR_PTR(-ENOMEM);
139 }
a10423b8 140
28fbcfa0 141 return &array->map;
28fbcfa0
AS
142}
143
144/* Called from syscall or from eBPF program */
145static void *array_map_lookup_elem(struct bpf_map *map, void *key)
146{
147 struct bpf_array *array = container_of(map, struct bpf_array, map);
148 u32 index = *(u32 *)key;
149
a10423b8 150 if (unlikely(index >= array->map.max_entries))
28fbcfa0
AS
151 return NULL;
152
b2157399 153 return array->value + array->elem_size * (index & array->index_mask);
28fbcfa0
AS
154}
155
d8eca5bb
DB
156static int array_map_direct_value_addr(const struct bpf_map *map, u64 *imm,
157 u32 off)
158{
159 struct bpf_array *array = container_of(map, struct bpf_array, map);
160
161 if (map->max_entries != 1)
162 return -ENOTSUPP;
163 if (off >= map->value_size)
164 return -EINVAL;
165
166 *imm = (unsigned long)array->value;
167 return 0;
168}
169
170static int array_map_direct_value_meta(const struct bpf_map *map, u64 imm,
171 u32 *off)
172{
173 struct bpf_array *array = container_of(map, struct bpf_array, map);
174 u64 base = (unsigned long)array->value;
175 u64 range = array->elem_size;
176
177 if (map->max_entries != 1)
178 return -ENOTSUPP;
179 if (imm < base || imm >= base + range)
180 return -ENOENT;
181
182 *off = imm - base;
183 return 0;
184}
185
81ed18ab
AS
186/* emit BPF instructions equivalent to C code of array_map_lookup_elem() */
187static u32 array_map_gen_lookup(struct bpf_map *map, struct bpf_insn *insn_buf)
188{
b2157399 189 struct bpf_array *array = container_of(map, struct bpf_array, map);
81ed18ab 190 struct bpf_insn *insn = insn_buf;
fad73a1a 191 u32 elem_size = round_up(map->value_size, 8);
81ed18ab
AS
192 const int ret = BPF_REG_0;
193 const int map_ptr = BPF_REG_1;
194 const int index = BPF_REG_2;
195
196 *insn++ = BPF_ALU64_IMM(BPF_ADD, map_ptr, offsetof(struct bpf_array, value));
197 *insn++ = BPF_LDX_MEM(BPF_W, ret, index, 0);
b2157399
AS
198 if (map->unpriv_array) {
199 *insn++ = BPF_JMP_IMM(BPF_JGE, ret, map->max_entries, 4);
200 *insn++ = BPF_ALU32_IMM(BPF_AND, ret, array->index_mask);
201 } else {
202 *insn++ = BPF_JMP_IMM(BPF_JGE, ret, map->max_entries, 3);
203 }
fad73a1a
MKL
204
205 if (is_power_of_2(elem_size)) {
81ed18ab
AS
206 *insn++ = BPF_ALU64_IMM(BPF_LSH, ret, ilog2(elem_size));
207 } else {
208 *insn++ = BPF_ALU64_IMM(BPF_MUL, ret, elem_size);
209 }
210 *insn++ = BPF_ALU64_REG(BPF_ADD, ret, map_ptr);
211 *insn++ = BPF_JMP_IMM(BPF_JA, 0, 0, 1);
212 *insn++ = BPF_MOV64_IMM(ret, 0);
213 return insn - insn_buf;
214}
215
a10423b8
AS
216/* Called from eBPF program */
217static void *percpu_array_map_lookup_elem(struct bpf_map *map, void *key)
218{
219 struct bpf_array *array = container_of(map, struct bpf_array, map);
220 u32 index = *(u32 *)key;
221
222 if (unlikely(index >= array->map.max_entries))
223 return NULL;
224
b2157399 225 return this_cpu_ptr(array->pptrs[index & array->index_mask]);
a10423b8
AS
226}
227
15a07b33
AS
228int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value)
229{
230 struct bpf_array *array = container_of(map, struct bpf_array, map);
231 u32 index = *(u32 *)key;
232 void __percpu *pptr;
233 int cpu, off = 0;
234 u32 size;
235
236 if (unlikely(index >= array->map.max_entries))
237 return -ENOENT;
238
239 /* per_cpu areas are zero-filled and bpf programs can only
240 * access 'value_size' of them, so copying rounded areas
241 * will not leak any kernel data
242 */
243 size = round_up(map->value_size, 8);
244 rcu_read_lock();
b2157399 245 pptr = array->pptrs[index & array->index_mask];
15a07b33
AS
246 for_each_possible_cpu(cpu) {
247 bpf_long_memcpy(value + off, per_cpu_ptr(pptr, cpu), size);
248 off += size;
249 }
250 rcu_read_unlock();
251 return 0;
252}
253
28fbcfa0
AS
254/* Called from syscall */
255static int array_map_get_next_key(struct bpf_map *map, void *key, void *next_key)
256{
257 struct bpf_array *array = container_of(map, struct bpf_array, map);
8fe45924 258 u32 index = key ? *(u32 *)key : U32_MAX;
28fbcfa0
AS
259 u32 *next = (u32 *)next_key;
260
261 if (index >= array->map.max_entries) {
262 *next = 0;
263 return 0;
264 }
265
266 if (index == array->map.max_entries - 1)
267 return -ENOENT;
268
269 *next = index + 1;
270 return 0;
271}
272
273/* Called from syscall or from eBPF program */
274static int array_map_update_elem(struct bpf_map *map, void *key, void *value,
275 u64 map_flags)
276{
277 struct bpf_array *array = container_of(map, struct bpf_array, map);
278 u32 index = *(u32 *)key;
96049f3a 279 char *val;
28fbcfa0 280
96049f3a 281 if (unlikely((map_flags & ~BPF_F_LOCK) > BPF_EXIST))
28fbcfa0
AS
282 /* unknown flags */
283 return -EINVAL;
284
a10423b8 285 if (unlikely(index >= array->map.max_entries))
28fbcfa0
AS
286 /* all elements were pre-allocated, cannot insert a new one */
287 return -E2BIG;
288
96049f3a 289 if (unlikely(map_flags & BPF_NOEXIST))
daaf427c 290 /* all elements already exist */
28fbcfa0
AS
291 return -EEXIST;
292
96049f3a
AS
293 if (unlikely((map_flags & BPF_F_LOCK) &&
294 !map_value_has_spin_lock(map)))
295 return -EINVAL;
296
297 if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
b2157399 298 memcpy(this_cpu_ptr(array->pptrs[index & array->index_mask]),
a10423b8 299 value, map->value_size);
96049f3a
AS
300 } else {
301 val = array->value +
302 array->elem_size * (index & array->index_mask);
303 if (map_flags & BPF_F_LOCK)
304 copy_map_value_locked(map, val, value, false);
305 else
306 copy_map_value(map, val, value);
307 }
28fbcfa0
AS
308 return 0;
309}
310
15a07b33
AS
311int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value,
312 u64 map_flags)
313{
314 struct bpf_array *array = container_of(map, struct bpf_array, map);
315 u32 index = *(u32 *)key;
316 void __percpu *pptr;
317 int cpu, off = 0;
318 u32 size;
319
320 if (unlikely(map_flags > BPF_EXIST))
321 /* unknown flags */
322 return -EINVAL;
323
324 if (unlikely(index >= array->map.max_entries))
325 /* all elements were pre-allocated, cannot insert a new one */
326 return -E2BIG;
327
328 if (unlikely(map_flags == BPF_NOEXIST))
329 /* all elements already exist */
330 return -EEXIST;
331
332 /* the user space will provide round_up(value_size, 8) bytes that
333 * will be copied into per-cpu area. bpf programs can only access
334 * value_size of it. During lookup the same extra bytes will be
335 * returned or zeros which were zero-filled by percpu_alloc,
336 * so no kernel data leaks possible
337 */
338 size = round_up(map->value_size, 8);
339 rcu_read_lock();
b2157399 340 pptr = array->pptrs[index & array->index_mask];
15a07b33
AS
341 for_each_possible_cpu(cpu) {
342 bpf_long_memcpy(per_cpu_ptr(pptr, cpu), value + off, size);
343 off += size;
344 }
345 rcu_read_unlock();
346 return 0;
347}
348
28fbcfa0
AS
349/* Called from syscall or from eBPF program */
350static int array_map_delete_elem(struct bpf_map *map, void *key)
351{
352 return -EINVAL;
353}
354
355/* Called when map->refcnt goes to zero, either from workqueue or from syscall */
356static void array_map_free(struct bpf_map *map)
357{
358 struct bpf_array *array = container_of(map, struct bpf_array, map);
359
360 /* at this point bpf_prog->aux->refcnt == 0 and this map->refcnt == 0,
361 * so the programs (can be more than one that used this map) were
362 * disconnected from events. Wait for outstanding programs to complete
363 * and free the array
364 */
365 synchronize_rcu();
366
a10423b8
AS
367 if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
368 bpf_array_free_percpu(array);
369
d407bd25 370 bpf_map_area_free(array);
28fbcfa0
AS
371}
372
a26ca7c9
MKL
373static void array_map_seq_show_elem(struct bpf_map *map, void *key,
374 struct seq_file *m)
375{
376 void *value;
377
378 rcu_read_lock();
379
380 value = array_map_lookup_elem(map, key);
381 if (!value) {
382 rcu_read_unlock();
383 return;
384 }
385
2824ecb7
DB
386 if (map->btf_key_type_id)
387 seq_printf(m, "%u: ", *(u32 *)key);
9b2cf328 388 btf_type_seq_show(map->btf, map->btf_value_type_id, value, m);
a26ca7c9
MKL
389 seq_puts(m, "\n");
390
391 rcu_read_unlock();
392}
393
c7b27c37
YS
394static void percpu_array_map_seq_show_elem(struct bpf_map *map, void *key,
395 struct seq_file *m)
396{
397 struct bpf_array *array = container_of(map, struct bpf_array, map);
398 u32 index = *(u32 *)key;
399 void __percpu *pptr;
400 int cpu;
401
402 rcu_read_lock();
403
404 seq_printf(m, "%u: {\n", *(u32 *)key);
405 pptr = array->pptrs[index & array->index_mask];
406 for_each_possible_cpu(cpu) {
407 seq_printf(m, "\tcpu%d: ", cpu);
408 btf_type_seq_show(map->btf, map->btf_value_type_id,
409 per_cpu_ptr(pptr, cpu), m);
410 seq_puts(m, "\n");
411 }
412 seq_puts(m, "}\n");
413
414 rcu_read_unlock();
415}
416
e8d2bec0 417static int array_map_check_btf(const struct bpf_map *map,
1b2b234b 418 const struct btf *btf,
e8d2bec0
DB
419 const struct btf_type *key_type,
420 const struct btf_type *value_type)
a26ca7c9 421{
a26ca7c9
MKL
422 u32 int_data;
423
2824ecb7
DB
424 /* One exception for keyless BTF: .bss/.data/.rodata map */
425 if (btf_type_is_void(key_type)) {
426 if (map->map_type != BPF_MAP_TYPE_ARRAY ||
427 map->max_entries != 1)
428 return -EINVAL;
429
430 if (BTF_INFO_KIND(value_type->info) != BTF_KIND_DATASEC)
431 return -EINVAL;
432
433 return 0;
434 }
435
e8d2bec0 436 if (BTF_INFO_KIND(key_type->info) != BTF_KIND_INT)
a26ca7c9
MKL
437 return -EINVAL;
438
439 int_data = *(u32 *)(key_type + 1);
e8d2bec0
DB
440 /* bpf array can only take a u32 key. This check makes sure
441 * that the btf matches the attr used during map_create.
a26ca7c9 442 */
e8d2bec0 443 if (BTF_INT_BITS(int_data) != 32 || BTF_INT_OFFSET(int_data))
a26ca7c9
MKL
444 return -EINVAL;
445
446 return 0;
447}
448
40077e0c 449const struct bpf_map_ops array_map_ops = {
ad46061f 450 .map_alloc_check = array_map_alloc_check,
28fbcfa0
AS
451 .map_alloc = array_map_alloc,
452 .map_free = array_map_free,
453 .map_get_next_key = array_map_get_next_key,
454 .map_lookup_elem = array_map_lookup_elem,
455 .map_update_elem = array_map_update_elem,
456 .map_delete_elem = array_map_delete_elem,
81ed18ab 457 .map_gen_lookup = array_map_gen_lookup,
d8eca5bb
DB
458 .map_direct_value_addr = array_map_direct_value_addr,
459 .map_direct_value_meta = array_map_direct_value_meta,
a26ca7c9
MKL
460 .map_seq_show_elem = array_map_seq_show_elem,
461 .map_check_btf = array_map_check_btf,
28fbcfa0
AS
462};
463
40077e0c 464const struct bpf_map_ops percpu_array_map_ops = {
ad46061f 465 .map_alloc_check = array_map_alloc_check,
a10423b8
AS
466 .map_alloc = array_map_alloc,
467 .map_free = array_map_free,
468 .map_get_next_key = array_map_get_next_key,
469 .map_lookup_elem = percpu_array_map_lookup_elem,
470 .map_update_elem = array_map_update_elem,
471 .map_delete_elem = array_map_delete_elem,
c7b27c37 472 .map_seq_show_elem = percpu_array_map_seq_show_elem,
e8d2bec0 473 .map_check_btf = array_map_check_btf,
a10423b8
AS
474};
475
ad46061f 476static int fd_array_map_alloc_check(union bpf_attr *attr)
04fd61ab 477{
2a36f0b9 478 /* only file descriptors can be stored in this type of map */
04fd61ab 479 if (attr->value_size != sizeof(u32))
ad46061f 480 return -EINVAL;
591fe988
DB
481 /* Program read-only/write-only not supported for special maps yet. */
482 if (attr->map_flags & (BPF_F_RDONLY_PROG | BPF_F_WRONLY_PROG))
483 return -EINVAL;
ad46061f 484 return array_map_alloc_check(attr);
04fd61ab
AS
485}
486
2a36f0b9 487static void fd_array_map_free(struct bpf_map *map)
04fd61ab
AS
488{
489 struct bpf_array *array = container_of(map, struct bpf_array, map);
490 int i;
491
492 synchronize_rcu();
493
494 /* make sure it's empty */
495 for (i = 0; i < array->map.max_entries; i++)
2a36f0b9 496 BUG_ON(array->ptrs[i] != NULL);
d407bd25
DB
497
498 bpf_map_area_free(array);
04fd61ab
AS
499}
500
2a36f0b9 501static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
04fd61ab 502{
3b4a63f6 503 return ERR_PTR(-EOPNOTSUPP);
04fd61ab
AS
504}
505
14dc6f04
MKL
506/* only called from syscall */
507int bpf_fd_array_map_lookup_elem(struct bpf_map *map, void *key, u32 *value)
508{
509 void **elem, *ptr;
510 int ret = 0;
511
512 if (!map->ops->map_fd_sys_lookup_elem)
513 return -ENOTSUPP;
514
515 rcu_read_lock();
516 elem = array_map_lookup_elem(map, key);
517 if (elem && (ptr = READ_ONCE(*elem)))
518 *value = map->ops->map_fd_sys_lookup_elem(ptr);
519 else
520 ret = -ENOENT;
521 rcu_read_unlock();
522
523 return ret;
524}
525
04fd61ab 526/* only called from syscall */
d056a788
DB
527int bpf_fd_array_map_update_elem(struct bpf_map *map, struct file *map_file,
528 void *key, void *value, u64 map_flags)
04fd61ab
AS
529{
530 struct bpf_array *array = container_of(map, struct bpf_array, map);
2a36f0b9 531 void *new_ptr, *old_ptr;
04fd61ab
AS
532 u32 index = *(u32 *)key, ufd;
533
534 if (map_flags != BPF_ANY)
535 return -EINVAL;
536
537 if (index >= array->map.max_entries)
538 return -E2BIG;
539
540 ufd = *(u32 *)value;
d056a788 541 new_ptr = map->ops->map_fd_get_ptr(map, map_file, ufd);
2a36f0b9
WN
542 if (IS_ERR(new_ptr))
543 return PTR_ERR(new_ptr);
04fd61ab 544
2a36f0b9
WN
545 old_ptr = xchg(array->ptrs + index, new_ptr);
546 if (old_ptr)
547 map->ops->map_fd_put_ptr(old_ptr);
04fd61ab
AS
548
549 return 0;
550}
551
2a36f0b9 552static int fd_array_map_delete_elem(struct bpf_map *map, void *key)
04fd61ab
AS
553{
554 struct bpf_array *array = container_of(map, struct bpf_array, map);
2a36f0b9 555 void *old_ptr;
04fd61ab
AS
556 u32 index = *(u32 *)key;
557
558 if (index >= array->map.max_entries)
559 return -E2BIG;
560
2a36f0b9
WN
561 old_ptr = xchg(array->ptrs + index, NULL);
562 if (old_ptr) {
563 map->ops->map_fd_put_ptr(old_ptr);
04fd61ab
AS
564 return 0;
565 } else {
566 return -ENOENT;
567 }
568}
569
d056a788
DB
570static void *prog_fd_array_get_ptr(struct bpf_map *map,
571 struct file *map_file, int fd)
2a36f0b9
WN
572{
573 struct bpf_array *array = container_of(map, struct bpf_array, map);
574 struct bpf_prog *prog = bpf_prog_get(fd);
d056a788 575
2a36f0b9
WN
576 if (IS_ERR(prog))
577 return prog;
578
579 if (!bpf_prog_array_compatible(array, prog)) {
580 bpf_prog_put(prog);
581 return ERR_PTR(-EINVAL);
582 }
d056a788 583
2a36f0b9
WN
584 return prog;
585}
586
587static void prog_fd_array_put_ptr(void *ptr)
588{
1aacde3d 589 bpf_prog_put(ptr);
2a36f0b9
WN
590}
591
14dc6f04
MKL
592static u32 prog_fd_array_sys_lookup_elem(void *ptr)
593{
594 return ((struct bpf_prog *)ptr)->aux->id;
595}
596
04fd61ab 597/* decrement refcnt of all bpf_progs that are stored in this map */
ba6b8de4 598static void bpf_fd_array_map_clear(struct bpf_map *map)
04fd61ab
AS
599{
600 struct bpf_array *array = container_of(map, struct bpf_array, map);
601 int i;
602
603 for (i = 0; i < array->map.max_entries; i++)
2a36f0b9 604 fd_array_map_delete_elem(map, &i);
04fd61ab
AS
605}
606
a7c19db3
YS
607static void prog_array_map_seq_show_elem(struct bpf_map *map, void *key,
608 struct seq_file *m)
609{
610 void **elem, *ptr;
611 u32 prog_id;
612
613 rcu_read_lock();
614
615 elem = array_map_lookup_elem(map, key);
616 if (elem) {
617 ptr = READ_ONCE(*elem);
618 if (ptr) {
619 seq_printf(m, "%u: ", *(u32 *)key);
620 prog_id = prog_fd_array_sys_lookup_elem(ptr);
621 btf_type_seq_show(map->btf, map->btf_value_type_id,
622 &prog_id, m);
623 seq_puts(m, "\n");
624 }
625 }
626
627 rcu_read_unlock();
628}
629
40077e0c 630const struct bpf_map_ops prog_array_map_ops = {
ad46061f
JK
631 .map_alloc_check = fd_array_map_alloc_check,
632 .map_alloc = array_map_alloc,
2a36f0b9 633 .map_free = fd_array_map_free,
04fd61ab 634 .map_get_next_key = array_map_get_next_key,
2a36f0b9 635 .map_lookup_elem = fd_array_map_lookup_elem,
2a36f0b9
WN
636 .map_delete_elem = fd_array_map_delete_elem,
637 .map_fd_get_ptr = prog_fd_array_get_ptr,
638 .map_fd_put_ptr = prog_fd_array_put_ptr,
14dc6f04 639 .map_fd_sys_lookup_elem = prog_fd_array_sys_lookup_elem,
ba6b8de4 640 .map_release_uref = bpf_fd_array_map_clear,
a7c19db3 641 .map_seq_show_elem = prog_array_map_seq_show_elem,
04fd61ab
AS
642};
643
3b1efb19
DB
644static struct bpf_event_entry *bpf_event_entry_gen(struct file *perf_file,
645 struct file *map_file)
ea317b26 646{
3b1efb19
DB
647 struct bpf_event_entry *ee;
648
858d68f1 649 ee = kzalloc(sizeof(*ee), GFP_ATOMIC);
3b1efb19
DB
650 if (ee) {
651 ee->event = perf_file->private_data;
652 ee->perf_file = perf_file;
653 ee->map_file = map_file;
654 }
655
656 return ee;
657}
658
659static void __bpf_event_entry_free(struct rcu_head *rcu)
660{
661 struct bpf_event_entry *ee;
662
663 ee = container_of(rcu, struct bpf_event_entry, rcu);
664 fput(ee->perf_file);
665 kfree(ee);
666}
667
668static void bpf_event_entry_free_rcu(struct bpf_event_entry *ee)
669{
670 call_rcu(&ee->rcu, __bpf_event_entry_free);
ea317b26
KX
671}
672
d056a788
DB
673static void *perf_event_fd_array_get_ptr(struct bpf_map *map,
674 struct file *map_file, int fd)
ea317b26 675{
3b1efb19
DB
676 struct bpf_event_entry *ee;
677 struct perf_event *event;
678 struct file *perf_file;
f91840a3 679 u64 value;
ea317b26 680
3b1efb19
DB
681 perf_file = perf_event_get(fd);
682 if (IS_ERR(perf_file))
683 return perf_file;
e03e7ee3 684
f91840a3 685 ee = ERR_PTR(-EOPNOTSUPP);
3b1efb19 686 event = perf_file->private_data;
97562633 687 if (perf_event_read_local(event, &value, NULL, NULL) == -EOPNOTSUPP)
3b1efb19
DB
688 goto err_out;
689
f91840a3
AS
690 ee = bpf_event_entry_gen(perf_file, map_file);
691 if (ee)
692 return ee;
693 ee = ERR_PTR(-ENOMEM);
3b1efb19
DB
694err_out:
695 fput(perf_file);
696 return ee;
ea317b26
KX
697}
698
699static void perf_event_fd_array_put_ptr(void *ptr)
700{
3b1efb19
DB
701 bpf_event_entry_free_rcu(ptr);
702}
703
704static void perf_event_fd_array_release(struct bpf_map *map,
705 struct file *map_file)
706{
707 struct bpf_array *array = container_of(map, struct bpf_array, map);
708 struct bpf_event_entry *ee;
709 int i;
710
711 rcu_read_lock();
712 for (i = 0; i < array->map.max_entries; i++) {
713 ee = READ_ONCE(array->ptrs[i]);
714 if (ee && ee->map_file == map_file)
715 fd_array_map_delete_elem(map, &i);
716 }
717 rcu_read_unlock();
ea317b26
KX
718}
719
40077e0c 720const struct bpf_map_ops perf_event_array_map_ops = {
ad46061f
JK
721 .map_alloc_check = fd_array_map_alloc_check,
722 .map_alloc = array_map_alloc,
3b1efb19 723 .map_free = fd_array_map_free,
ea317b26
KX
724 .map_get_next_key = array_map_get_next_key,
725 .map_lookup_elem = fd_array_map_lookup_elem,
ea317b26
KX
726 .map_delete_elem = fd_array_map_delete_elem,
727 .map_fd_get_ptr = perf_event_fd_array_get_ptr,
728 .map_fd_put_ptr = perf_event_fd_array_put_ptr,
3b1efb19 729 .map_release = perf_event_fd_array_release,
e8d2bec0 730 .map_check_btf = map_check_no_btf,
ea317b26
KX
731};
732
60d20f91 733#ifdef CONFIG_CGROUPS
4ed8ec52
MKL
734static void *cgroup_fd_array_get_ptr(struct bpf_map *map,
735 struct file *map_file /* not used */,
736 int fd)
737{
738 return cgroup_get_from_fd(fd);
739}
740
741static void cgroup_fd_array_put_ptr(void *ptr)
742{
743 /* cgroup_put free cgrp after a rcu grace period */
744 cgroup_put(ptr);
745}
746
747static void cgroup_fd_array_free(struct bpf_map *map)
748{
749 bpf_fd_array_map_clear(map);
750 fd_array_map_free(map);
751}
752
40077e0c 753const struct bpf_map_ops cgroup_array_map_ops = {
ad46061f
JK
754 .map_alloc_check = fd_array_map_alloc_check,
755 .map_alloc = array_map_alloc,
4ed8ec52
MKL
756 .map_free = cgroup_fd_array_free,
757 .map_get_next_key = array_map_get_next_key,
758 .map_lookup_elem = fd_array_map_lookup_elem,
759 .map_delete_elem = fd_array_map_delete_elem,
760 .map_fd_get_ptr = cgroup_fd_array_get_ptr,
761 .map_fd_put_ptr = cgroup_fd_array_put_ptr,
e8d2bec0 762 .map_check_btf = map_check_no_btf,
4ed8ec52 763};
4ed8ec52 764#endif
56f668df
MKL
765
766static struct bpf_map *array_of_map_alloc(union bpf_attr *attr)
767{
768 struct bpf_map *map, *inner_map_meta;
769
770 inner_map_meta = bpf_map_meta_alloc(attr->inner_map_fd);
771 if (IS_ERR(inner_map_meta))
772 return inner_map_meta;
773
ad46061f 774 map = array_map_alloc(attr);
56f668df
MKL
775 if (IS_ERR(map)) {
776 bpf_map_meta_free(inner_map_meta);
777 return map;
778 }
779
780 map->inner_map_meta = inner_map_meta;
781
782 return map;
783}
784
785static void array_of_map_free(struct bpf_map *map)
786{
787 /* map->inner_map_meta is only accessed by syscall which
788 * is protected by fdget/fdput.
789 */
790 bpf_map_meta_free(map->inner_map_meta);
791 bpf_fd_array_map_clear(map);
792 fd_array_map_free(map);
793}
794
795static void *array_of_map_lookup_elem(struct bpf_map *map, void *key)
796{
797 struct bpf_map **inner_map = array_map_lookup_elem(map, key);
798
799 if (!inner_map)
800 return NULL;
801
802 return READ_ONCE(*inner_map);
803}
804
7b0c2a05
DB
805static u32 array_of_map_gen_lookup(struct bpf_map *map,
806 struct bpf_insn *insn_buf)
807{
b2157399 808 struct bpf_array *array = container_of(map, struct bpf_array, map);
7b0c2a05
DB
809 u32 elem_size = round_up(map->value_size, 8);
810 struct bpf_insn *insn = insn_buf;
811 const int ret = BPF_REG_0;
812 const int map_ptr = BPF_REG_1;
813 const int index = BPF_REG_2;
814
815 *insn++ = BPF_ALU64_IMM(BPF_ADD, map_ptr, offsetof(struct bpf_array, value));
816 *insn++ = BPF_LDX_MEM(BPF_W, ret, index, 0);
b2157399
AS
817 if (map->unpriv_array) {
818 *insn++ = BPF_JMP_IMM(BPF_JGE, ret, map->max_entries, 6);
819 *insn++ = BPF_ALU32_IMM(BPF_AND, ret, array->index_mask);
820 } else {
821 *insn++ = BPF_JMP_IMM(BPF_JGE, ret, map->max_entries, 5);
822 }
7b0c2a05
DB
823 if (is_power_of_2(elem_size))
824 *insn++ = BPF_ALU64_IMM(BPF_LSH, ret, ilog2(elem_size));
825 else
826 *insn++ = BPF_ALU64_IMM(BPF_MUL, ret, elem_size);
827 *insn++ = BPF_ALU64_REG(BPF_ADD, ret, map_ptr);
828 *insn++ = BPF_LDX_MEM(BPF_DW, ret, ret, 0);
829 *insn++ = BPF_JMP_IMM(BPF_JEQ, ret, 0, 1);
830 *insn++ = BPF_JMP_IMM(BPF_JA, 0, 0, 1);
831 *insn++ = BPF_MOV64_IMM(ret, 0);
832
833 return insn - insn_buf;
834}
835
40077e0c 836const struct bpf_map_ops array_of_maps_map_ops = {
ad46061f 837 .map_alloc_check = fd_array_map_alloc_check,
56f668df
MKL
838 .map_alloc = array_of_map_alloc,
839 .map_free = array_of_map_free,
840 .map_get_next_key = array_map_get_next_key,
841 .map_lookup_elem = array_of_map_lookup_elem,
842 .map_delete_elem = fd_array_map_delete_elem,
843 .map_fd_get_ptr = bpf_map_fd_get_ptr,
844 .map_fd_put_ptr = bpf_map_fd_put_ptr,
14dc6f04 845 .map_fd_sys_lookup_elem = bpf_map_fd_sys_lookup_elem,
7b0c2a05 846 .map_gen_lookup = array_of_map_gen_lookup,
e8d2bec0 847 .map_check_btf = map_check_no_btf,
56f668df 848};