summaryrefslogtreecommitdiff
path: root/tools/lib/bpf/btf.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-06-17 09:18:14 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2026-06-17 09:18:14 +0100
commit9c87e61e3c5797277407ba5eae4eac8a52be3fa3 (patch)
treee3f902cb5363b5b90ab74a4b7e26fafbc15aaeaf /tools/lib/bpf/btf.c
parentb85966adbf5de0668a815c6e3527f87e0c387fb4 (diff)
parente4287bf34f97a88c7d9322f5bde828724c073a6b (diff)
downloadlinux-next-9c87e61e3c5797277407ba5eae4eac8a52be3fa3.tar.gz
linux-next-9c87e61e3c5797277407ba5eae4eac8a52be3fa3.zip
Merge tag 'bpf-next-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
Pull bpf updates from Alexei Starovoitov: "Major changes: - Recover from BPF arena page faults using a scratch page and add ptep_try_set() for lockless empty-slot installs on x86 and arm64. This allows BPF kfuncs to access arena pointers directly. The 'arena_direct_access' stable branch was created for this work and was pulled into sched-ext and bpf-next trees (Tejun Heo, Kumar Kartikeya Dwivedi) - Lift old restriction and support 6+ arguments in BPF programs and kfuncs on x86 and arm64 (Yonghong Song, Puranjay Mohan) Other features and fixes: - Add 24-bit BTF vlen and reclaim unused bits in the BTF UAPI to ease addition of new BTF kinds (Alan Maguire) - Raise the maximum BPF call chain depth from 8 to 16 frames (Alexei Starovoitov) - Refactor object relationship tracking in the verifier and fix a dynptr use-after-free bug (Amery Hung) - Harden the signed program loader and reject exclusive maps as inner maps (Daniel Borkmann) - Replace the verifier min/max bounds fields with a circular number (cnum) representation and improve 32->64 bit range refinements (Eduard Zingerman) - Introduce the arena library and runtime (libarena) with a buddy allocator, rbtree and SPMC queue data structures, ASAN support and a parallel test harness. Allow subprograms to return arena pointers and switch to a BTF type-tag based __arena annotation (Emil Tsalapatis) - Cache build IDs in the sleepable stackmap path and avoid faultable build ID reads under mm locks (Ihor Solodrai) - Introduce the tracing_multi link to attach a single BPF program to many kernel functions at once. Allow specifying the uprobe_multi target via FD (Jiri Olsa) - Extend the bpf_list family of kfuncs with bpf_list_add/del(), and bpf_list_is_first/is_last/empty() (Kaitao Cheng) - Extend the BPF syscall with common attributes support for prog_load, btf_load and map_create (Leon Hwang) - Wrap rhashtable as BPF map (Mykyta Yatsenko, Herbert Xu) - Add sleepable support for tracepoint programs and fix deadlocks in LRU map due to NMI reentry (Mykyta Yatsenko) - Fix OOB access in bpf_flow_keys, fix nullness analysis of inner arrays, enforce write checks for global subprograms (Nuoqi Gui) - Report the maximum combined stack depth and print a breakdown of instructions processed per subprogram (Paul Chaignon) - Add an XDP load-balancer benchmark and arm64 JIT support for stack arguments (Puranjay Mohan) - Add kfuncs to traverse over wakeup_sources (Samuel Wu) - Allow sleepable BPF programs to use LPM trie maps directly (Vlad Poenaru) - Many more fixes and cleanups across the verifier, BTF, sockmap, devmap, bpffs, security hooks, s390/riscv/loongarch JITs, rqspinlock, libbpf, bpftool, selftests" * tag 'bpf-next-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next: (336 commits) selftests/bpf: Work around llvm stack overflow in crypto progs selftests/bpf: add test for bpf_msg_pop_data() overflow bpf, sockmap: fix integer overflow in bpf_msg_pop_data() bounds check sockmap: Fix use-after-free in udp_bpf_recvmsg() bpf, sockmap: keep sk_msg copy state in sync bpf, sockmap: Fix wrong rsge offset in bpf_msg_push_data() bpf, sockmap: reject overflowing copy + len in bpf_msg_push_data() selftsets/bpf: Retry map update on helper_fill_hashmap() selftests/bpf: Add test for sleepable lsm_cgroup rejection selftests/bpf: Add test to verify the fix for bpf_setsockopt() helper bpf: Fix bpf_get/setsockopt to tos for ipv4-mapped ipv6 socket selftests/bpf: Avoid static LLVM linking for cross builds selftests/bpf: Use common CFLAGS for urandom_read selftests/bpf: Initialize operation name before use tools/bpf: build: Append extra cflags libbpf: Initialize CFLAGS before including Makefile.include bpftool: Append extra host flags bpftool: Avoid adding EXTRA_CFLAGS to HOST_CFLAGS bpftool: Pass host flags to bootstrap libbpf selftests/bpf: correct CONFIG_PPC64 macro name in comment ...
Diffstat (limited to 'tools/lib/bpf/btf.c')
-rw-r--r--tools/lib/bpf/btf.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index ceb57b46a878..823bce895178 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -421,7 +421,7 @@ static int btf_type_size_unknown(const struct btf *btf, const struct btf_type *t
{
__u32 l_cnt = btf->hdr.layout_len / sizeof(struct btf_layout);
struct btf_layout *l = btf->layout;
- __u16 vlen = btf_vlen(t);
+ __u32 vlen = btf_vlen(t);
__u32 kind = btf_kind(t);
/* Fall back to base BTF if needed as they share layout information */
@@ -454,7 +454,7 @@ static int btf_type_size_unknown(const struct btf *btf, const struct btf_type *t
static int btf_type_size(const struct btf *btf, const struct btf_type *t)
{
const int base_size = sizeof(struct btf_type);
- __u16 vlen = btf_vlen(t);
+ __u32 vlen = btf_vlen(t);
switch (btf_kind(t)) {
case BTF_KIND_FWD:
@@ -506,7 +506,7 @@ static int btf_bswap_type_rest(struct btf_type *t)
struct btf_array *a;
struct btf_param *p;
struct btf_enum *e;
- __u16 vlen = btf_vlen(t);
+ __u32 vlen = btf_vlen(t);
int i;
switch (btf_kind(t)) {
@@ -1007,7 +1007,7 @@ int btf__align_of(const struct btf *btf, __u32 id)
case BTF_KIND_STRUCT:
case BTF_KIND_UNION: {
const struct btf_member *m = btf_members(t);
- __u16 vlen = btf_vlen(t);
+ __u32 vlen = btf_vlen(t);
int i, max_align = 1, align;
for (i = 0; i < vlen; i++, m++) {
@@ -2121,9 +2121,12 @@ static void *btf_add_type_mem(struct btf *btf, size_t add_sz)
btf->hdr.type_len, UINT_MAX, add_sz);
}
-static void btf_type_inc_vlen(struct btf_type *t)
+static int btf_type_inc_vlen(struct btf_type *t)
{
+ if (btf_vlen(t) == BTF_MAX_VLEN)
+ return -ENOSPC;
t->info = btf_type_info(btf_kind(t), btf_vlen(t) + 1, btf_kflag(t));
+ return 0;
}
static void btf_hdr_update_type_len(struct btf *btf, int new_len)
@@ -2652,6 +2655,8 @@ int btf__add_field(struct btf *btf, const char *name, int type_id,
t = btf_last_type(btf);
if (!btf_is_composite(t))
return libbpf_err(-EINVAL);
+ if (btf_vlen(t) == BTF_MAX_VLEN)
+ return libbpf_err(-ENOSPC);
if (validate_type_id(type_id))
return libbpf_err(-EINVAL);
@@ -2686,6 +2691,7 @@ int btf__add_field(struct btf *btf, const char *name, int type_id,
/* btf_add_type_mem can invalidate t pointer */
t = btf_last_type(btf);
+
/* update parent type's vlen and kflag */
t->info = btf_type_info(btf_kind(t), btf_vlen(t) + 1, is_bitfield || btf_kflag(t));
@@ -2796,7 +2802,9 @@ int btf__add_enum_value(struct btf *btf, const char *name, __s64 value)
/* update parent type's vlen */
t = btf_last_type(btf);
- btf_type_inc_vlen(t);
+ err = btf_type_inc_vlen(t);
+ if (err)
+ return libbpf_err(err);
/* if negative value, set signedness to signed */
if (value < 0)
@@ -2873,7 +2881,9 @@ int btf__add_enum64_value(struct btf *btf, const char *name, __u64 value)
/* update parent type's vlen */
t = btf_last_type(btf);
- btf_type_inc_vlen(t);
+ err = btf_type_inc_vlen(t);
+ if (err)
+ return libbpf_err(err);
btf_hdr_update_type_len(btf, btf->hdr.type_len + sz);
return 0;
@@ -3115,7 +3125,9 @@ int btf__add_func_param(struct btf *btf, const char *name, int type_id)
/* update parent type's vlen */
t = btf_last_type(btf);
- btf_type_inc_vlen(t);
+ err = btf_type_inc_vlen(t);
+ if (err)
+ return libbpf_err(err);
btf_hdr_update_type_len(btf, btf->hdr.type_len + sz);
return 0;
@@ -3257,7 +3269,9 @@ int btf__add_datasec_var_info(struct btf *btf, int var_type_id, __u32 offset, __
/* update parent type's vlen */
t = btf_last_type(btf);
- btf_type_inc_vlen(t);
+ err = btf_type_inc_vlen(t);
+ if (err)
+ return libbpf_err(err);
btf_hdr_update_type_len(btf, btf->hdr.type_len + sz);
return 0;
@@ -4311,7 +4325,7 @@ static long btf_hash_enum(struct btf_type *t)
static bool btf_equal_enum_members(struct btf_type *t1, struct btf_type *t2)
{
const struct btf_enum *m1, *m2;
- __u16 vlen;
+ __u32 vlen;
int i;
vlen = btf_vlen(t1);
@@ -4329,7 +4343,7 @@ static bool btf_equal_enum_members(struct btf_type *t1, struct btf_type *t2)
static bool btf_equal_enum64_members(struct btf_type *t1, struct btf_type *t2)
{
const struct btf_enum64 *m1, *m2;
- __u16 vlen;
+ __u32 vlen;
int i;
vlen = btf_vlen(t1);
@@ -4406,7 +4420,7 @@ static long btf_hash_struct(struct btf_type *t)
static bool btf_shallow_equal_struct(struct btf_type *t1, struct btf_type *t2)
{
const struct btf_member *m1, *m2;
- __u16 vlen;
+ __u32 vlen;
int i;
if (!btf_equal_common(t1, t2))
@@ -4482,7 +4496,7 @@ static bool btf_compat_array(struct btf_type *t1, struct btf_type *t2)
static long btf_hash_fnproto(struct btf_type *t)
{
const struct btf_param *member = btf_params(t);
- __u16 vlen = btf_vlen(t);
+ __u32 vlen = btf_vlen(t);
long h = btf_hash_common(t);
int i;
@@ -4504,7 +4518,7 @@ static long btf_hash_fnproto(struct btf_type *t)
static bool btf_equal_fnproto(struct btf_type *t1, struct btf_type *t2)
{
const struct btf_param *m1, *m2;
- __u16 vlen;
+ __u32 vlen;
int i;
if (!btf_equal_common(t1, t2))
@@ -4530,7 +4544,7 @@ static bool btf_equal_fnproto(struct btf_type *t1, struct btf_type *t2)
static bool btf_compat_fnproto(struct btf_type *t1, struct btf_type *t2)
{
const struct btf_param *m1, *m2;
- __u16 vlen;
+ __u32 vlen;
int i;
/* skip return type ID */
@@ -4578,12 +4592,14 @@ static int btf_dedup_prep(struct btf_dedup *d)
case BTF_KIND_RESTRICT:
case BTF_KIND_PTR:
case BTF_KIND_FWD:
- case BTF_KIND_TYPEDEF:
case BTF_KIND_FUNC:
case BTF_KIND_FLOAT:
case BTF_KIND_TYPE_TAG:
h = btf_hash_common(t);
break;
+ case BTF_KIND_TYPEDEF:
+ h = btf_hash_typedef(t);
+ break;
case BTF_KIND_INT:
case BTF_KIND_DECL_TAG:
h = btf_hash_int_decl_tag(t);
@@ -5077,7 +5093,7 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
case BTF_KIND_STRUCT:
case BTF_KIND_UNION: {
const struct btf_member *cand_m, *canon_m;
- __u16 vlen;
+ __u32 vlen;
if (!btf_shallow_equal_struct(cand_type, canon_type))
return 0;
@@ -5105,7 +5121,7 @@ static int btf_dedup_is_equiv(struct btf_dedup *d, __u32 cand_id,
case BTF_KIND_FUNC_PROTO: {
const struct btf_param *cand_p, *canon_p;
- __u16 vlen;
+ __u32 vlen;
if (!btf_compat_fnproto(cand_type, canon_type))
return 0;
@@ -5439,7 +5455,7 @@ static int btf_dedup_ref_type(struct btf_dedup *d, __u32 type_id)
case BTF_KIND_FUNC_PROTO: {
struct btf_param *param;
- __u16 vlen;
+ __u32 vlen;
int i;
ref_type_id = btf_dedup_ref_type(d, t->type);