aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/btf.c108
-rw-r--r--kernel/bpf/syscall.c24
2 files changed, 121 insertions, 11 deletions
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index fa0dce0452e7..40950b6bf395 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -11,6 +11,7 @@
11#include <linux/file.h> 11#include <linux/file.h>
12#include <linux/uaccess.h> 12#include <linux/uaccess.h>
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/idr.h>
14#include <linux/bpf_verifier.h> 15#include <linux/bpf_verifier.h>
15#include <linux/btf.h> 16#include <linux/btf.h>
16 17
@@ -179,6 +180,9 @@
179 i < btf_type_vlen(struct_type); \ 180 i < btf_type_vlen(struct_type); \
180 i++, member++) 181 i++, member++)
181 182
183static DEFINE_IDR(btf_idr);
184static DEFINE_SPINLOCK(btf_idr_lock);
185
182struct btf { 186struct btf {
183 union { 187 union {
184 struct btf_header *hdr; 188 struct btf_header *hdr;
@@ -193,6 +197,8 @@ struct btf {
193 u32 types_size; 197 u32 types_size;
194 u32 data_size; 198 u32 data_size;
195 refcount_t refcnt; 199 refcount_t refcnt;
200 u32 id;
201 struct rcu_head rcu;
196}; 202};
197 203
198enum verifier_phase { 204enum verifier_phase {
@@ -598,6 +604,42 @@ static int btf_add_type(struct btf_verifier_env *env, struct btf_type *t)
598 return 0; 604 return 0;
599} 605}
600 606
607static int btf_alloc_id(struct btf *btf)
608{
609 int id;
610
611 idr_preload(GFP_KERNEL);
612 spin_lock_bh(&btf_idr_lock);
613 id = idr_alloc_cyclic(&btf_idr, btf, 1, INT_MAX, GFP_ATOMIC);
614 if (id > 0)
615 btf->id = id;
616 spin_unlock_bh(&btf_idr_lock);
617 idr_preload_end();
618
619 if (WARN_ON_ONCE(!id))
620 return -ENOSPC;
621
622 return id > 0 ? 0 : id;
623}
624
625static void btf_free_id(struct btf *btf)
626{
627 unsigned long flags;
628
629 /*
630 * In map-in-map, calling map_delete_elem() on outer
631 * map will call bpf_map_put on the inner map.
632 * It will then eventually call btf_free_id()
633 * on the inner map. Some of the map_delete_elem()
634 * implementation may have irq disabled, so
635 * we need to use the _irqsave() version instead
636 * of the _bh() version.
637 */
638 spin_lock_irqsave(&btf_idr_lock, flags);
639 idr_remove(&btf_idr, btf->id);
640 spin_unlock_irqrestore(&btf_idr_lock, flags);
641}
642
601static void btf_free(struct btf *btf) 643static void btf_free(struct btf *btf)
602{ 644{
603 kvfree(btf->types); 645 kvfree(btf->types);
@@ -607,15 +649,19 @@ static void btf_free(struct btf *btf)
607 kfree(btf); 649 kfree(btf);
608} 650}
609 651
610static void btf_get(struct btf *btf) 652static void btf_free_rcu(struct rcu_head *rcu)
611{ 653{
612 refcount_inc(&btf->refcnt); 654 struct btf *btf = container_of(rcu, struct btf, rcu);
655
656 btf_free(btf);
613} 657}
614 658
615void btf_put(struct btf *btf) 659void btf_put(struct btf *btf)
616{ 660{
617 if (btf && refcount_dec_and_test(&btf->refcnt)) 661 if (btf && refcount_dec_and_test(&btf->refcnt)) {
618 btf_free(btf); 662 btf_free_id(btf);
663 call_rcu(&btf->rcu, btf_free_rcu);
664 }
619} 665}
620 666
621static int env_resolve_init(struct btf_verifier_env *env) 667static int env_resolve_init(struct btf_verifier_env *env)
@@ -2006,10 +2052,15 @@ const struct file_operations btf_fops = {
2006 .release = btf_release, 2052 .release = btf_release,
2007}; 2053};
2008 2054
2055static int __btf_new_fd(struct btf *btf)
2056{
2057 return anon_inode_getfd("btf", &btf_fops, btf, O_RDONLY | O_CLOEXEC);
2058}
2059
2009int btf_new_fd(const union bpf_attr *attr) 2060int btf_new_fd(const union bpf_attr *attr)
2010{ 2061{
2011 struct btf *btf; 2062 struct btf *btf;
2012 int fd; 2063 int ret;
2013 2064
2014 btf = btf_parse(u64_to_user_ptr(attr->btf), 2065 btf = btf_parse(u64_to_user_ptr(attr->btf),
2015 attr->btf_size, attr->btf_log_level, 2066 attr->btf_size, attr->btf_log_level,
@@ -2018,12 +2069,23 @@ int btf_new_fd(const union bpf_attr *attr)
2018 if (IS_ERR(btf)) 2069 if (IS_ERR(btf))
2019 return PTR_ERR(btf); 2070 return PTR_ERR(btf);
2020 2071
2021 fd = anon_inode_getfd("btf", &btf_fops, btf, 2072 ret = btf_alloc_id(btf);
2022 O_RDONLY | O_CLOEXEC); 2073 if (ret) {
2023 if (fd < 0) 2074 btf_free(btf);
2075 return ret;
2076 }
2077
2078 /*
2079 * The BTF ID is published to the userspace.
2080 * All BTF free must go through call_rcu() from
2081 * now on (i.e. free by calling btf_put()).
2082 */
2083
2084 ret = __btf_new_fd(btf);
2085 if (ret < 0)
2024 btf_put(btf); 2086 btf_put(btf);
2025 2087
2026 return fd; 2088 return ret;
2027} 2089}
2028 2090
2029struct btf *btf_get_by_fd(int fd) 2091struct btf *btf_get_by_fd(int fd)
@@ -2042,7 +2104,7 @@ struct btf *btf_get_by_fd(int fd)
2042 } 2104 }
2043 2105
2044 btf = f.file->private_data; 2106 btf = f.file->private_data;
2045 btf_get(btf); 2107 refcount_inc(&btf->refcnt);
2046 fdput(f); 2108 fdput(f);
2047 2109
2048 return btf; 2110 return btf;
@@ -2062,3 +2124,29 @@ int btf_get_info_by_fd(const struct btf *btf,
2062 2124
2063 return 0; 2125 return 0;
2064} 2126}
2127
2128int btf_get_fd_by_id(u32 id)
2129{
2130 struct btf *btf;
2131 int fd;
2132
2133 rcu_read_lock();
2134 btf = idr_find(&btf_idr, id);
2135 if (!btf || !refcount_inc_not_zero(&btf->refcnt))
2136 btf = ERR_PTR(-ENOENT);
2137 rcu_read_unlock();
2138
2139 if (IS_ERR(btf))
2140 return PTR_ERR(btf);
2141
2142 fd = __btf_new_fd(btf);
2143 if (fd < 0)
2144 btf_put(btf);
2145
2146 return fd;
2147}
2148
2149u32 btf_id(const struct btf *btf)
2150{
2151 return btf->id;
2152}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 9b87198deea2..31c4092da277 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -252,7 +252,6 @@ static void bpf_map_free_deferred(struct work_struct *work)
252 252
253 bpf_map_uncharge_memlock(map); 253 bpf_map_uncharge_memlock(map);
254 security_bpf_map_free(map); 254 security_bpf_map_free(map);
255 btf_put(map->btf);
256 /* implementation dependent freeing */ 255 /* implementation dependent freeing */
257 map->ops->map_free(map); 256 map->ops->map_free(map);
258} 257}
@@ -273,6 +272,7 @@ static void __bpf_map_put(struct bpf_map *map, bool do_idr_lock)
273 if (atomic_dec_and_test(&map->refcnt)) { 272 if (atomic_dec_and_test(&map->refcnt)) {
274 /* bpf_map_free_id() must be called first */ 273 /* bpf_map_free_id() must be called first */
275 bpf_map_free_id(map, do_idr_lock); 274 bpf_map_free_id(map, do_idr_lock);
275 btf_put(map->btf);
276 INIT_WORK(&map->work, bpf_map_free_deferred); 276 INIT_WORK(&map->work, bpf_map_free_deferred);
277 schedule_work(&map->work); 277 schedule_work(&map->work);
278 } 278 }
@@ -2002,6 +2002,12 @@ static int bpf_map_get_info_by_fd(struct bpf_map *map,
2002 info.map_flags = map->map_flags; 2002 info.map_flags = map->map_flags;
2003 memcpy(info.name, map->name, sizeof(map->name)); 2003 memcpy(info.name, map->name, sizeof(map->name));
2004 2004
2005 if (map->btf) {
2006 info.btf_id = btf_id(map->btf);
2007 info.btf_key_id = map->btf_key_id;
2008 info.btf_value_id = map->btf_value_id;
2009 }
2010
2005 if (bpf_map_is_dev_bound(map)) { 2011 if (bpf_map_is_dev_bound(map)) {
2006 err = bpf_map_offload_info_fill(&info, map); 2012 err = bpf_map_offload_info_fill(&info, map);
2007 if (err) 2013 if (err)
@@ -2059,6 +2065,19 @@ static int bpf_btf_load(const union bpf_attr *attr)
2059 return btf_new_fd(attr); 2065 return btf_new_fd(attr);
2060} 2066}
2061 2067
2068#define BPF_BTF_GET_FD_BY_ID_LAST_FIELD btf_id
2069
2070static int bpf_btf_get_fd_by_id(const union bpf_attr *attr)
2071{
2072 if (CHECK_ATTR(BPF_BTF_GET_FD_BY_ID))
2073 return -EINVAL;
2074
2075 if (!capable(CAP_SYS_ADMIN))
2076 return -EPERM;
2077
2078 return btf_get_fd_by_id(attr->btf_id);
2079}
2080
2062SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size) 2081SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
2063{ 2082{
2064 union bpf_attr attr = {}; 2083 union bpf_attr attr = {};
@@ -2142,6 +2161,9 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
2142 case BPF_BTF_LOAD: 2161 case BPF_BTF_LOAD:
2143 err = bpf_btf_load(&attr); 2162 err = bpf_btf_load(&attr);
2144 break; 2163 break;
2164 case BPF_BTF_GET_FD_BY_ID:
2165 err = bpf_btf_get_fd_by_id(&attr);
2166 break;
2145 default: 2167 default:
2146 err = -EINVAL; 2168 err = -EINVAL;
2147 break; 2169 break;