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.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 4ca46df19c9a..fe23dc5a3ec4 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -11,6 +11,7 @@
11 */ 11 */
12#include <linux/bpf.h> 12#include <linux/bpf.h>
13#include <linux/bpf_trace.h> 13#include <linux/bpf_trace.h>
14#include <linux/btf.h>
14#include <linux/syscalls.h> 15#include <linux/syscalls.h>
15#include <linux/slab.h> 16#include <linux/slab.h>
16#include <linux/sched/signal.h> 17#include <linux/sched/signal.h>
@@ -26,6 +27,7 @@
26#include <linux/cred.h> 27#include <linux/cred.h>
27#include <linux/timekeeping.h> 28#include <linux/timekeeping.h>
28#include <linux/ctype.h> 29#include <linux/ctype.h>
30#include <linux/btf.h>
29 31
30#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 || \
31 (map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \ 33 (map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
@@ -250,6 +252,7 @@ static void bpf_map_free_deferred(struct work_struct *work)
250 252
251 bpf_map_uncharge_memlock(map); 253 bpf_map_uncharge_memlock(map);
252 security_bpf_map_free(map); 254 security_bpf_map_free(map);
255 btf_put(map->btf);
253 /* implementation dependent freeing */ 256 /* implementation dependent freeing */
254 map->ops->map_free(map); 257 map->ops->map_free(map);
255} 258}
@@ -415,7 +418,7 @@ static int bpf_obj_name_cpy(char *dst, const char *src)
415 return 0; 418 return 0;
416} 419}
417 420
418#define BPF_MAP_CREATE_LAST_FIELD map_ifindex 421#define BPF_MAP_CREATE_LAST_FIELD btf_value_id
419/* called via syscall */ 422/* called via syscall */
420static int map_create(union bpf_attr *attr) 423static int map_create(union bpf_attr *attr)
421{ 424{
@@ -449,6 +452,33 @@ static int map_create(union bpf_attr *attr)
449 atomic_set(&map->refcnt, 1); 452 atomic_set(&map->refcnt, 1);
450 atomic_set(&map->usercnt, 1); 453 atomic_set(&map->usercnt, 1);
451 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
452 err = security_bpf_map_alloc(map); 482 err = security_bpf_map_alloc(map);
453 if (err) 483 if (err)
454 goto free_map_nouncharge; 484 goto free_map_nouncharge;
@@ -481,6 +511,7 @@ free_map:
481free_map_sec: 511free_map_sec:
482 security_bpf_map_free(map); 512 security_bpf_map_free(map);
483free_map_nouncharge: 513free_map_nouncharge:
514 btf_put(map->btf);
484 map->ops->map_free(map); 515 map->ops->map_free(map);
485 return err; 516 return err;
486} 517}
@@ -2016,6 +2047,8 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
2016 else if (f.file->f_op == &bpf_map_fops) 2047 else if (f.file->f_op == &bpf_map_fops)
2017 err = bpf_map_get_info_by_fd(f.file->private_data, attr, 2048 err = bpf_map_get_info_by_fd(f.file->private_data, attr,
2018 uattr); 2049 uattr);
2050 else if (f.file->f_op == &btf_fops)
2051 err = btf_get_info_by_fd(f.file->private_data, attr, uattr);
2019 else 2052 else
2020 err = -EINVAL; 2053 err = -EINVAL;
2021 2054
@@ -2023,6 +2056,19 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
2023 return err; 2056 return err;
2024} 2057}
2025 2058
2059#define BPF_BTF_LOAD_LAST_FIELD btf_log_level
2060
2061static int bpf_btf_load(const union bpf_attr *attr)
2062{
2063 if (CHECK_ATTR(BPF_BTF_LOAD))
2064 return -EINVAL;
2065
2066 if (!capable(CAP_SYS_ADMIN))
2067 return -EPERM;
2068
2069 return btf_new_fd(attr);
2070}
2071
2026SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) 2072SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
2027{ 2073{
2028 union bpf_attr attr = {}; 2074 union bpf_attr attr = {};
@@ -2103,6 +2149,9 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
2103 case BPF_RAW_TRACEPOINT_OPEN: 2149 case BPF_RAW_TRACEPOINT_OPEN:
2104 err = bpf_raw_tracepoint_open(&attr); 2150 err = bpf_raw_tracepoint_open(&attr);
2105 break; 2151 break;
2152 case BPF_BTF_LOAD:
2153 err = bpf_btf_load(&attr);
2154 break;
2106 default: 2155 default:
2107 err = -EINVAL; 2156 err = -EINVAL;
2108 break; 2157 break;