diff options
Diffstat (limited to 'kernel/bpf/syscall.c')
-rw-r--r-- | kernel/bpf/syscall.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index c286e75ec087..bfcde949c7f8 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
@@ -255,7 +255,6 @@ static void bpf_map_free_deferred(struct work_struct *work) | |||
255 | 255 | ||
256 | bpf_map_uncharge_memlock(map); | 256 | bpf_map_uncharge_memlock(map); |
257 | security_bpf_map_free(map); | 257 | security_bpf_map_free(map); |
258 | btf_put(map->btf); | ||
259 | /* implementation dependent freeing */ | 258 | /* implementation dependent freeing */ |
260 | map->ops->map_free(map); | 259 | map->ops->map_free(map); |
261 | } | 260 | } |
@@ -276,6 +275,7 @@ static void __bpf_map_put(struct bpf_map *map, bool do_idr_lock) | |||
276 | if (atomic_dec_and_test(&map->refcnt)) { | 275 | if (atomic_dec_and_test(&map->refcnt)) { |
277 | /* bpf_map_free_id() must be called first */ | 276 | /* bpf_map_free_id() must be called first */ |
278 | bpf_map_free_id(map, do_idr_lock); | 277 | bpf_map_free_id(map, do_idr_lock); |
278 | btf_put(map->btf); | ||
279 | INIT_WORK(&map->work, bpf_map_free_deferred); | 279 | INIT_WORK(&map->work, bpf_map_free_deferred); |
280 | schedule_work(&map->work); | 280 | schedule_work(&map->work); |
281 | } | 281 | } |
@@ -2011,6 +2011,12 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map, | |||
2011 | info.map_flags = map->map_flags; | 2011 | info.map_flags = map->map_flags; |
2012 | memcpy(info.name, map->name, sizeof(map->name)); | 2012 | memcpy(info.name, map->name, sizeof(map->name)); |
2013 | 2013 | ||
2014 | if (map->btf) { | ||
2015 | info.btf_id = btf_id(map->btf); | ||
2016 | info.btf_key_id = map->btf_key_id; | ||
2017 | info.btf_value_id = map->btf_value_id; | ||
2018 | } | ||
2019 | |||
2014 | if (bpf_map_is_dev_bound(map)) { | 2020 | if (bpf_map_is_dev_bound(map)) { |
2015 | err = bpf_map_offload_info_fill(&info, map); | 2021 | err = bpf_map_offload_info_fill(&info, map); |
2016 | if (err) | 2022 | if (err) |
@@ -2024,6 +2030,21 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map, | |||
2024 | return 0; | 2030 | return 0; |
2025 | } | 2031 | } |
2026 | 2032 | ||
2033 | static int bpf_btf_get_info_by_fd(struct btf *btf, | ||
2034 | const union bpf_attr *attr, | ||
2035 | union bpf_attr __user *uattr) | ||
2036 | { | ||
2037 | struct bpf_btf_info __user *uinfo = u64_to_user_ptr(attr->info.info); | ||
2038 | u32 info_len = attr->info.info_len; | ||
2039 | int err; | ||
2040 | |||
2041 | err = check_uarg_tail_zero(uinfo, sizeof(*uinfo), info_len); | ||
2042 | if (err) | ||
2043 | return err; | ||
2044 | |||
2045 | return btf_get_info_by_fd(btf, attr, uattr); | ||
2046 | } | ||
2047 | |||
2027 | #define BPF_OBJ_GET_INFO_BY_FD_LAST_FIELD info.info | 2048 | #define BPF_OBJ_GET_INFO_BY_FD_LAST_FIELD info.info |
2028 | 2049 | ||
2029 | static int bpf_obj_get_info_by_fd(const union bpf_attr *attr, | 2050 | static int bpf_obj_get_info_by_fd(const union bpf_attr *attr, |
@@ -2047,7 +2068,7 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr, | |||
2047 | err = bpf_map_get_info_by_fd(f.file->private_data, attr, | 2068 | err = bpf_map_get_info_by_fd(f.file->private_data, attr, |
2048 | uattr); | 2069 | uattr); |
2049 | else if (f.file->f_op == &btf_fops) | 2070 | else if (f.file->f_op == &btf_fops) |
2050 | err = btf_get_info_by_fd(f.file->private_data, attr, uattr); | 2071 | err = bpf_btf_get_info_by_fd(f.file->private_data, attr, uattr); |
2051 | else | 2072 | else |
2052 | err = -EINVAL; | 2073 | err = -EINVAL; |
2053 | 2074 | ||
@@ -2068,6 +2089,19 @@ static int bpf_btf_load(const union bpf_attr *attr) | |||
2068 | return btf_new_fd(attr); | 2089 | return btf_new_fd(attr); |
2069 | } | 2090 | } |
2070 | 2091 | ||
2092 | #define BPF_BTF_GET_FD_BY_ID_LAST_FIELD btf_id | ||
2093 | |||
2094 | static int bpf_btf_get_fd_by_id(const union bpf_attr *attr) | ||
2095 | { | ||
2096 | if (CHECK_ATTR(BPF_BTF_GET_FD_BY_ID)) | ||
2097 | return -EINVAL; | ||
2098 | |||
2099 | if (!capable(CAP_SYS_ADMIN)) | ||
2100 | return -EPERM; | ||
2101 | |||
2102 | return btf_get_fd_by_id(attr->btf_id); | ||
2103 | } | ||
2104 | |||
2071 | SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) | 2105 | SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) |
2072 | { | 2106 | { |
2073 | union bpf_attr attr = {}; | 2107 | union bpf_attr attr = {}; |
@@ -2151,6 +2185,9 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz | |||
2151 | case BPF_BTF_LOAD: | 2185 | case BPF_BTF_LOAD: |
2152 | err = bpf_btf_load(&attr); | 2186 | err = bpf_btf_load(&attr); |
2153 | break; | 2187 | break; |
2188 | case BPF_BTF_GET_FD_BY_ID: | ||
2189 | err = bpf_btf_get_fd_by_id(&attr); | ||
2190 | break; | ||
2154 | default: | 2191 | default: |
2155 | err = -EINVAL; | 2192 | err = -EINVAL; |
2156 | break; | 2193 | break; |