diff options
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r-- | kernel/bpf/syscall.c | 32 |
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 */ |
421 | static int map_create(union bpf_attr *attr) | 423 | static 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: | |||
482 | free_map_sec: | 511 | free_map_sec: |
483 | security_bpf_map_free(map); | 512 | security_bpf_map_free(map); |
484 | free_map_nouncharge: | 513 | free_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 | } |