aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/syscall.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r--kernel/bpf/syscall.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 0a4924a0a8da..fe23dc5a3ec4 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -27,6 +27,7 @@
27#include <linux/cred.h> 27#include <linux/cred.h>
28#include <linux/timekeeping.h> 28#include <linux/timekeeping.h>
29#include <linux/ctype.h> 29#include <linux/ctype.h>
30#include <linux/btf.h>
30 31
31#define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY || \ 32#define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY || \
32 (map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \ 33 (map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
@@ -251,6 +252,7 @@ static void bpf_map_free_deferred(struct work_struct *work)
251 252
252 bpf_map_uncharge_memlock(map); 253 bpf_map_uncharge_memlock(map);
253 security_bpf_map_free(map); 254 security_bpf_map_free(map);
255 btf_put(map->btf);
254 /* implementation dependent freeing */ 256 /* implementation dependent freeing */
255 map->ops->map_free(map); 257 map->ops->map_free(map);
256} 258}
@@ -416,7 +418,7 @@ static int bpf_obj_name_cpy(char *dst, const char *src)
416 return 0; 418 return 0;
417} 419}
418 420
419#define BPF_MAP_CREATE_LAST_FIELD map_ifindex 421#define BPF_MAP_CREATE_LAST_FIELD btf_value_id
420/* called via syscall */ 422/* called via syscall */
421static int map_create(union bpf_attr *attr) 423static int map_create(union bpf_attr *attr)
422{ 424{
@@ -450,6 +452,33 @@ static int map_create(union bpf_attr *attr)
450 atomic_set(&map->refcnt, 1); 452 atomic_set(&map->refcnt, 1);
451 atomic_set(&map->usercnt, 1); 453 atomic_set(&map->usercnt, 1);
452 454
455 if (bpf_map_support_seq_show(map) &&
456 (attr->btf_key_id || attr->btf_value_id)) {
457 struct btf *btf;
458
459 if (!attr->btf_key_id || !attr->btf_value_id) {
460 err = -EINVAL;
461 goto free_map_nouncharge;
462 }
463
464 btf = btf_get_by_fd(attr->btf_fd);
465 if (IS_ERR(btf)) {
466 err = PTR_ERR(btf);
467 goto free_map_nouncharge;
468 }
469
470 err = map->ops->map_check_btf(map, btf, attr->btf_key_id,
471 attr->btf_value_id);
472 if (err) {
473 btf_put(btf);
474 goto free_map_nouncharge;
475 }
476
477 map->btf = btf;
478 map->btf_key_id = attr->btf_key_id;
479 map->btf_value_id = attr->btf_value_id;
480 }
481
453 err = security_bpf_map_alloc(map); 482 err = security_bpf_map_alloc(map);
454 if (err) 483 if (err)
455 goto free_map_nouncharge; 484 goto free_map_nouncharge;
@@ -482,6 +511,7 @@ free_map:
482free_map_sec: 511free_map_sec:
483 security_bpf_map_free(map); 512 security_bpf_map_free(map);
484free_map_nouncharge: 513free_map_nouncharge:
514 btf_put(map->btf);
485 map->ops->map_free(map); 515 map->ops->map_free(map);
486 return err; 516 return err;
487} 517}