* [PATCH v2 bpf-next 0/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits
@ 2026-04-16 14:38 Alan Maguire
2026-04-16 14:38 ` [PATCH v2 bpf-next 1/8] " Alan Maguire
` (7 more replies)
0 siblings, 8 replies; 21+ messages in thread
From: Alan Maguire @ 2026-04-16 14:38 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, Alan Maguire
Currently BTF types can have a maximum of 65535 vlen-specified
objects. While this limit has not yet been surpassed for existing
cases (struct/union fields, enum values, function arguments and
datasec), upcoming BTF location information - specifically inline
sites - will hit that limit. Utilize unused BTF info bits in
struct btf_type to increase limit to 24-bits (over 16 million).
This is more than an order of magnitude greater than inline
site counts for the kernel (~400,000) so should be enough for
the near future at least.
Similarly, struct btf_type uses 5 bits for BTF kind values;
currently we use 20, but BTF location information will consume
another 3, and conceivably providing better support for Rust
types in BTF (now that modules can be built using Rust) could
push us close to the max of 31. Use 2 unused bits to provide
a max possible kind of 127.
Patch 1 handles UAPI and kernel-related changes.
Patch 2 updates libbpf to have btf_vlen() return a __u32 instead
of __u16 and updates consumers in libbpf accordingly.
Patch 3 adds a BTF feature check for extended vlen/kind support;
loading BTF with a vlen > 65535 which will fail if the kernel
does not support extended vlen.
Patch 4 cleans up __u16 vlen usage in bpftool.
Patch 5 tests the BTF extended vlen/kind feature check.
Patch 6 fixes up a test that relies on BTF info overflowing
maximum kind value; fix up the expected error to be an
invalid kind rather than (now impossible) invalid btf_info.
Changes since v1 [1]:
- added redundant macros to UAPI in case enum switch for BTF_MAX*
values causes problems (sashiko, patch 1)
- updated feature test to use BTF loading rather than vmlinux BTF
lookup, in line with other BTF feature tests (sashiko, patch 3)
- fixed up a few more kernel, libbpf, bpftool instances of __u16 usage
(bpf bot, sashiko, patches 1, 2, 4)
- fixed up sanitize selftest cleanup (Mykyta, patch 5)
- used unlikely-to-be-used kind (sashiko, patch 6)
- fixed a few lingering selftests uses of __u16 for kind (patch 7)
- update btf.rst with new vlen, kind sizes (patch 8)
[1] https://lore.kernel.org/bpf/20260414195019.684531-1-alan.maguire@oracle.com/
Alan Maguire (8):
bpf: Extend BTF UAPI vlen, kinds to use unused bits
libbpf: Adjust btf_vlen() to return a __u32
libbpf: Add feature for kernel extended vlen/kind support
bpftool: Support 24-bit vlen
selftests/bpf: Test BTF sanitization rejection for invalid vlen
selftests/bpf: Fix up btf/invalid test for extended kind
selftests/bpf: Fix up __u16 vlen assumptions
Documentation/bpf: Update btf doc with updated vlen, kind sizes
Documentation/bpf/btf.rst | 6 +-
include/linux/btf.h | 4 +-
include/uapi/linux/btf.h | 34 +++++----
kernel/bpf/btf.c | 27 +++----
tools/bpf/bpftool/btf.c | 17 ++---
tools/bpf/bpftool/btf_dumper.c | 4 +-
tools/bpf/bpftool/gen.c | 16 +++--
tools/include/uapi/linux/btf.h | 34 +++++----
tools/lib/bpf/btf.c | 47 ++++++++-----
tools/lib/bpf/btf.h | 2 +-
tools/lib/bpf/btf_dump.c | 24 +++----
tools/lib/bpf/features.c | 43 ++++++++++++
tools/lib/bpf/libbpf.c | 17 ++++-
tools/lib/bpf/libbpf_internal.h | 2 +
tools/lib/bpf/relo_core.c | 16 ++---
tools/testing/selftests/bpf/prog_tests/btf.c | 8 +--
.../bpf/prog_tests/btf_dedup_split.c | 2 +-
.../selftests/bpf/prog_tests/btf_sanitize.c | 70 ++++++++++++++++++-
tools/testing/selftests/bpf/test_progs.c | 2 +-
19 files changed, 261 insertions(+), 114 deletions(-)
--
2.39.3
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH v2 bpf-next 1/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits
2026-04-16 14:38 [PATCH v2 bpf-next 0/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
@ 2026-04-16 14:38 ` Alan Maguire
2026-04-16 15:54 ` Alexei Starovoitov
2026-04-16 19:05 ` sashiko-bot
2026-04-16 14:38 ` [PATCH v2 bpf-next 2/8] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
` (6 subsequent siblings)
7 siblings, 2 replies; 21+ messages in thread
From: Alan Maguire @ 2026-04-16 14:38 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, Alan Maguire
BTF maximum vlen is encoded using 16 bits with a maximum vlen
of 65535. This has sufficed for structs, function parameters
and enumerated type values. However, with upcoming BTF location
information - in particular information about inline sites -
this limit is surpassed. Use bits 16-23 - currently unused in
BTF info - to extend to 24 bits, giving a max vlen of (2^24 - 1),
or 16 million.
Also extend BTF kind encoding from 5 to 7 bits, giving a maximum
available number of kinds of 128. Since with the BTF location work
we use another 3 kinds, we are fast approaching the current limit
of 32.
Convert BTF_MAX_* values to enums to allow them to be encoded in
kernel BTF; this will allow us to detect if the running kernel
supports a 24-bit vlen or not. Add one for max _possible_
(not used) kind. Provide backwards-compatible macros just in
case.
Fix up a few places in the kernel where a 16-bit vlen is assumed;
remove BTF_INFO_MASK as now all bits are used.
The vlen expansion was suggested by Andrii in [1]; the kind expansion
is tackled here too as it may be needed also to support new kinds
in BTF.
[1] https://lore.kernel.org/bpf/CAEf4BzZx=X6vGqcA8SPU6D+v6k+TR=ZewebXMuXtpmML058piw@mail.gmail.com/
Suggested-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
include/linux/btf.h | 4 ++--
include/uapi/linux/btf.h | 34 ++++++++++++++++++++++------------
kernel/bpf/btf.c | 27 ++++++++++-----------------
tools/include/uapi/linux/btf.h | 34 ++++++++++++++++++++++------------
4 files changed, 56 insertions(+), 43 deletions(-)
diff --git a/include/linux/btf.h b/include/linux/btf.h
index 48108471c5b1..c82d0d689059 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -415,12 +415,12 @@ static inline bool btf_type_is_array(const struct btf_type *t)
return BTF_INFO_KIND(t->info) == BTF_KIND_ARRAY;
}
-static inline u16 btf_type_vlen(const struct btf_type *t)
+static inline u32 btf_type_vlen(const struct btf_type *t)
{
return BTF_INFO_VLEN(t->info);
}
-static inline u16 btf_vlen(const struct btf_type *t)
+static inline u32 btf_vlen(const struct btf_type *t)
{
return btf_type_vlen(t);
}
diff --git a/include/uapi/linux/btf.h b/include/uapi/linux/btf.h
index 638615ebddc2..5b138ef1b5f3 100644
--- a/include/uapi/linux/btf.h
+++ b/include/uapi/linux/btf.h
@@ -33,20 +33,30 @@ struct btf_header {
__u32 layout_len; /* length of layout section */
};
-/* Max # of type identifier */
-#define BTF_MAX_TYPE 0x000fffff
-/* Max offset into the string section */
-#define BTF_MAX_NAME_OFFSET 0x00ffffff
-/* Max # of struct/union/enum members or func args */
-#define BTF_MAX_VLEN 0xffff
+enum btf_max {
+ /* Max possible kind */
+ BTF_MAX_KIND = 0x0000007f,
+ /* Max # of type identifier */
+ BTF_MAX_TYPE = 0x000fffff,
+ /* Max offset into the string section */
+ BTF_MAX_NAME_OFFSET = 0x00ffffff,
+ /* Max # of struct/union/enum members or func args */
+ BTF_MAX_VLEN = 0x00ffffff,
+};
+
+/*
+ * Macros needed for backwards compatibility; enum above ensures values
+ * make it into BTF.
+ */
+#define BTF_MAX_TYPE BTF_MAX_TYPE
+#define BTF_MAX_NAME_OFFSET BTF_MAX_NAME_OFFSET
+#define BTF_MAX_VLEN BTF_MAX_VLEN
struct btf_type {
__u32 name_off;
/* "info" bits arrangement
- * bits 0-15: vlen (e.g. # of struct's members)
- * bits 16-23: unused
- * bits 24-28: kind (e.g. int, ptr, array...etc)
- * bits 29-30: unused
+ * bits 0-23: vlen (e.g. # of struct's members)
+ * bits 24-30: kind (e.g. int, ptr, array...etc)
* bit 31: kind_flag, currently used by
* struct, union, enum, fwd, enum64,
* decl_tag and type_tag
@@ -65,8 +75,8 @@ struct btf_type {
};
};
-#define BTF_INFO_KIND(info) (((info) >> 24) & 0x1f)
-#define BTF_INFO_VLEN(info) ((info) & 0xffff)
+#define BTF_INFO_KIND(info) (((info) >> 24) & 0x7f)
+#define BTF_INFO_VLEN(info) ((info) & 0xffffff)
#define BTF_INFO_KFLAG(info) ((info) >> 31)
enum {
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index a62d78581207..fedead837b9a 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -182,7 +182,6 @@
#define BITS_ROUNDUP_BYTES(bits) \
(BITS_ROUNDDOWN_BYTES(bits) + !!BITS_PER_BYTE_MASKED(bits))
-#define BTF_INFO_MASK 0x9f00ffff
#define BTF_INT_MASK 0x0fffffff
#define BTF_TYPE_ID_VALID(type_id) ((type_id) <= BTF_MAX_TYPE)
#define BTF_STR_OFFSET_VALID(name_off) ((name_off) <= BTF_MAX_NAME_OFFSET)
@@ -289,7 +288,7 @@ enum verifier_phase {
struct resolve_vertex {
const struct btf_type *t;
u32 type_id;
- u16 next_member;
+ u32 next_member;
};
enum visit_state {
@@ -2031,7 +2030,7 @@ static int env_stack_push(struct btf_verifier_env *env,
}
static void env_stack_set_next_member(struct btf_verifier_env *env,
- u16 next_member)
+ u32 next_member)
{
env->stack[env->top_stack - 1].next_member = next_member;
}
@@ -3293,7 +3292,7 @@ static s32 btf_struct_check_meta(struct btf_verifier_env *env,
struct btf *btf = env->btf;
u32 struct_size = t->size;
u32 offset;
- u16 i;
+ u32 i;
meta_needed = btf_type_vlen(t) * sizeof(*member);
if (meta_left < meta_needed) {
@@ -3369,7 +3368,7 @@ static int btf_struct_resolve(struct btf_verifier_env *env,
{
const struct btf_member *member;
int err;
- u16 i;
+ u32 i;
/* Before continue resolving the next_member,
* ensure the last member is indeed resolved to a
@@ -4447,7 +4446,7 @@ static s32 btf_enum_check_meta(struct btf_verifier_env *env,
const struct btf_enum *enums = btf_type_enum(t);
struct btf *btf = env->btf;
const char *fmt_str;
- u16 i, nr_enums;
+ u32 i, nr_enums;
u32 meta_needed;
nr_enums = btf_type_vlen(t);
@@ -4555,7 +4554,7 @@ static s32 btf_enum64_check_meta(struct btf_verifier_env *env,
const struct btf_enum64 *enums = btf_type_enum64(t);
struct btf *btf = env->btf;
const char *fmt_str;
- u16 i, nr_enums;
+ u32 i, nr_enums;
u32 meta_needed;
nr_enums = btf_type_vlen(t);
@@ -4683,7 +4682,7 @@ static void btf_func_proto_log(struct btf_verifier_env *env,
const struct btf_type *t)
{
const struct btf_param *args = (const struct btf_param *)(t + 1);
- u16 nr_args = btf_type_vlen(t), i;
+ u32 nr_args = btf_type_vlen(t), i;
btf_verifier_log(env, "return=%u args=(", t->type);
if (!nr_args) {
@@ -4929,7 +4928,7 @@ static int btf_datasec_resolve(struct btf_verifier_env *env,
{
const struct btf_var_secinfo *vsi;
struct btf *btf = env->btf;
- u16 i;
+ u32 i;
env->resolve_mode = RESOLVE_TBD;
for_each_vsi_from(i, v->next_member, v->t, vsi) {
@@ -5183,7 +5182,7 @@ static int btf_func_proto_check(struct btf_verifier_env *env,
const struct btf_type *ret_type;
const struct btf_param *args;
const struct btf *btf;
- u16 nr_args, i;
+ u32 nr_args, i;
int err;
btf = env->btf;
@@ -5278,7 +5277,7 @@ static int btf_func_check(struct btf_verifier_env *env,
const struct btf_type *proto_type;
const struct btf_param *args;
const struct btf *btf;
- u16 nr_args, i;
+ u32 nr_args, i;
btf = env->btf;
proto_type = btf_type_by_id(btf, t->type);
@@ -5336,12 +5335,6 @@ static s32 btf_check_meta(struct btf_verifier_env *env,
}
meta_left -= sizeof(*t);
- if (t->info & ~BTF_INFO_MASK) {
- btf_verifier_log(env, "[%u] Invalid btf_info:%x",
- env->log_type_id, t->info);
- return -EINVAL;
- }
-
if (BTF_INFO_KIND(t->info) > BTF_KIND_MAX ||
BTF_INFO_KIND(t->info) == BTF_KIND_UNKN) {
btf_verifier_log(env, "[%u] Invalid kind:%u",
diff --git a/tools/include/uapi/linux/btf.h b/tools/include/uapi/linux/btf.h
index 638615ebddc2..5b138ef1b5f3 100644
--- a/tools/include/uapi/linux/btf.h
+++ b/tools/include/uapi/linux/btf.h
@@ -33,20 +33,30 @@ struct btf_header {
__u32 layout_len; /* length of layout section */
};
-/* Max # of type identifier */
-#define BTF_MAX_TYPE 0x000fffff
-/* Max offset into the string section */
-#define BTF_MAX_NAME_OFFSET 0x00ffffff
-/* Max # of struct/union/enum members or func args */
-#define BTF_MAX_VLEN 0xffff
+enum btf_max {
+ /* Max possible kind */
+ BTF_MAX_KIND = 0x0000007f,
+ /* Max # of type identifier */
+ BTF_MAX_TYPE = 0x000fffff,
+ /* Max offset into the string section */
+ BTF_MAX_NAME_OFFSET = 0x00ffffff,
+ /* Max # of struct/union/enum members or func args */
+ BTF_MAX_VLEN = 0x00ffffff,
+};
+
+/*
+ * Macros needed for backwards compatibility; enum above ensures values
+ * make it into BTF.
+ */
+#define BTF_MAX_TYPE BTF_MAX_TYPE
+#define BTF_MAX_NAME_OFFSET BTF_MAX_NAME_OFFSET
+#define BTF_MAX_VLEN BTF_MAX_VLEN
struct btf_type {
__u32 name_off;
/* "info" bits arrangement
- * bits 0-15: vlen (e.g. # of struct's members)
- * bits 16-23: unused
- * bits 24-28: kind (e.g. int, ptr, array...etc)
- * bits 29-30: unused
+ * bits 0-23: vlen (e.g. # of struct's members)
+ * bits 24-30: kind (e.g. int, ptr, array...etc)
* bit 31: kind_flag, currently used by
* struct, union, enum, fwd, enum64,
* decl_tag and type_tag
@@ -65,8 +75,8 @@ struct btf_type {
};
};
-#define BTF_INFO_KIND(info) (((info) >> 24) & 0x1f)
-#define BTF_INFO_VLEN(info) ((info) & 0xffff)
+#define BTF_INFO_KIND(info) (((info) >> 24) & 0x7f)
+#define BTF_INFO_VLEN(info) ((info) & 0xffffff)
#define BTF_INFO_KFLAG(info) ((info) >> 31)
enum {
--
2.39.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 bpf-next 2/8] libbpf: Adjust btf_vlen() to return a __u32
2026-04-16 14:38 [PATCH v2 bpf-next 0/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
2026-04-16 14:38 ` [PATCH v2 bpf-next 1/8] " Alan Maguire
@ 2026-04-16 14:38 ` Alan Maguire
2026-04-16 15:27 ` bot+bpf-ci
2026-04-16 19:36 ` sashiko-bot
2026-04-16 14:38 ` [PATCH v2 bpf-next 3/8] libbpf: Add feature for kernel extended vlen/kind support Alan Maguire
` (5 subsequent siblings)
7 siblings, 2 replies; 21+ messages in thread
From: Alan Maguire @ 2026-04-16 14:38 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, Alan Maguire
Now that vlen is 24 bits, btf_vlen() must return a __u32.
Adjust use cases in libbpf accordingly. Also add error
handling to avoid vlen overflow in btf_type_inc_vlen().
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
tools/lib/bpf/btf.c | 47 ++++++++++++++++++++++++---------------
tools/lib/bpf/btf.h | 2 +-
tools/lib/bpf/btf_dump.c | 24 ++++++++++----------
tools/lib/bpf/relo_core.c | 16 ++++++-------
4 files changed, 50 insertions(+), 39 deletions(-)
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index ceb57b46a878..dfe72235e5dc 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)
@@ -2796,7 +2799,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 +2878,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 +3122,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 +3266,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 +4322,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 +4340,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 +4417,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 +4493,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 +4515,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 +4541,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 */
@@ -5077,7 +5088,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 +5116,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 +5450,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);
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index a1f8deca2603..1a31f2da947f 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -435,7 +435,7 @@ static inline __u16 btf_kind(const struct btf_type *t)
return BTF_INFO_KIND(t->info);
}
-static inline __u16 btf_vlen(const struct btf_type *t)
+static inline __u32 btf_vlen(const struct btf_type *t)
{
return BTF_INFO_VLEN(t->info);
}
diff --git a/tools/lib/bpf/btf_dump.c b/tools/lib/bpf/btf_dump.c
index 53c6624161d7..cc1ba65bb6c5 100644
--- a/tools/lib/bpf/btf_dump.c
+++ b/tools/lib/bpf/btf_dump.c
@@ -316,7 +316,7 @@ static int btf_dump_mark_referenced(struct btf_dump *d)
{
int i, j, n = btf__type_cnt(d->btf);
const struct btf_type *t;
- __u16 vlen;
+ __u32 vlen;
for (i = d->last_id + 1; i < n; i++) {
t = btf__type_by_id(d->btf, i);
@@ -485,7 +485,7 @@ static int btf_dump_order_type(struct btf_dump *d, __u32 id, bool through_ptr)
*/
struct btf_dump_type_aux_state *tstate = &d->type_states[id];
const struct btf_type *t;
- __u16 vlen;
+ __u32 vlen;
int err, i;
/* return true, letting typedefs know that it's ok to be emitted */
@@ -798,7 +798,7 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id)
*/
if (top_level_def || t->name_off == 0) {
const struct btf_member *m = btf_members(t);
- __u16 vlen = btf_vlen(t);
+ __u32 vlen = btf_vlen(t);
int i, new_cont_id;
new_cont_id = t->name_off == 0 ? cont_id : id;
@@ -820,7 +820,7 @@ static void btf_dump_emit_type(struct btf_dump *d, __u32 id, __u32 cont_id)
break;
case BTF_KIND_FUNC_PROTO: {
const struct btf_param *p = btf_params(t);
- __u16 n = btf_vlen(t);
+ __u32 n = btf_vlen(t);
int i;
btf_dump_emit_type(d, t->type, cont_id);
@@ -839,7 +839,7 @@ static bool btf_is_struct_packed(const struct btf *btf, __u32 id,
{
const struct btf_member *m;
int max_align = 1, align, i, bit_sz;
- __u16 vlen;
+ __u32 vlen;
m = btf_members(t);
vlen = btf_vlen(t);
@@ -973,7 +973,7 @@ static void btf_dump_emit_struct_def(struct btf_dump *d,
bool is_struct = btf_is_struct(t);
bool packed, prev_bitfield = false;
int align, i, off = 0;
- __u16 vlen = btf_vlen(t);
+ __u32 vlen = btf_vlen(t);
align = btf__align_of(d->btf, id);
packed = is_struct ? btf_is_struct_packed(d->btf, id, t) : 0;
@@ -1064,7 +1064,7 @@ static void btf_dump_emit_enum_fwd(struct btf_dump *d, __u32 id,
static void btf_dump_emit_enum32_val(struct btf_dump *d,
const struct btf_type *t,
- int lvl, __u16 vlen)
+ int lvl, __u32 vlen)
{
const struct btf_enum *v = btf_enum(t);
bool is_signed = btf_kflag(t);
@@ -1089,7 +1089,7 @@ static void btf_dump_emit_enum32_val(struct btf_dump *d,
static void btf_dump_emit_enum64_val(struct btf_dump *d,
const struct btf_type *t,
- int lvl, __u16 vlen)
+ int lvl, __u32 vlen)
{
const struct btf_enum64 *v = btf_enum64(t);
bool is_signed = btf_kflag(t);
@@ -1122,7 +1122,7 @@ static void btf_dump_emit_enum_def(struct btf_dump *d, __u32 id,
const struct btf_type *t,
int lvl)
{
- __u16 vlen = btf_vlen(t);
+ __u32 vlen = btf_vlen(t);
btf_dump_printf(d, "enum%s%s",
t->name_off ? " " : "",
@@ -1542,7 +1542,7 @@ static void btf_dump_emit_type_chain(struct btf_dump *d,
}
case BTF_KIND_FUNC_PROTO: {
const struct btf_param *p = btf_params(t);
- __u16 vlen = btf_vlen(t);
+ __u32 vlen = btf_vlen(t);
int i;
/*
@@ -2159,7 +2159,7 @@ static int btf_dump_struct_data(struct btf_dump *d,
const void *data)
{
const struct btf_member *m = btf_members(t);
- __u16 n = btf_vlen(t);
+ __u32 n = btf_vlen(t);
int i, err = 0;
/* note that we increment depth before calling btf_dump_print() below;
@@ -2449,7 +2449,7 @@ static int btf_dump_type_data_check_zero(struct btf_dump *d,
case BTF_KIND_STRUCT:
case BTF_KIND_UNION: {
const struct btf_member *m = btf_members(t);
- __u16 n = btf_vlen(t);
+ __u32 n = btf_vlen(t);
/* if any struct/union member is non-zero, the struct/union
* is considered non-zero and dumped.
diff --git a/tools/lib/bpf/relo_core.c b/tools/lib/bpf/relo_core.c
index 0ccc8f548cba..6ae3f2a15ad0 100644
--- a/tools/lib/bpf/relo_core.c
+++ b/tools/lib/bpf/relo_core.c
@@ -191,8 +191,8 @@ int __bpf_core_types_are_compat(const struct btf *local_btf, __u32 local_id,
case BTF_KIND_FUNC_PROTO: {
struct btf_param *local_p = btf_params(local_type);
struct btf_param *targ_p = btf_params(targ_type);
- __u16 local_vlen = btf_vlen(local_type);
- __u16 targ_vlen = btf_vlen(targ_type);
+ __u32 local_vlen = btf_vlen(local_type);
+ __u32 targ_vlen = btf_vlen(targ_type);
int i, err;
if (local_vlen != targ_vlen)
@@ -1457,8 +1457,8 @@ static bool bpf_core_names_match(const struct btf *local_btf, size_t local_name_
static int bpf_core_enums_match(const struct btf *local_btf, const struct btf_type *local_t,
const struct btf *targ_btf, const struct btf_type *targ_t)
{
- __u16 local_vlen = btf_vlen(local_t);
- __u16 targ_vlen = btf_vlen(targ_t);
+ __u32 local_vlen = btf_vlen(local_t);
+ __u32 targ_vlen = btf_vlen(targ_t);
int i, j;
if (local_t->size != targ_t->size)
@@ -1498,8 +1498,8 @@ static int bpf_core_composites_match(const struct btf *local_btf, const struct b
bool behind_ptr, int level)
{
const struct btf_member *local_m = btf_members(local_t);
- __u16 local_vlen = btf_vlen(local_t);
- __u16 targ_vlen = btf_vlen(targ_t);
+ __u32 local_vlen = btf_vlen(local_t);
+ __u32 targ_vlen = btf_vlen(targ_t);
int i, j, err;
if (local_vlen > targ_vlen)
@@ -1674,8 +1674,8 @@ int __bpf_core_types_match(const struct btf *local_btf, __u32 local_id, const st
case BTF_KIND_FUNC_PROTO: {
struct btf_param *local_p = btf_params(local_t);
struct btf_param *targ_p = btf_params(targ_t);
- __u16 local_vlen = btf_vlen(local_t);
- __u16 targ_vlen = btf_vlen(targ_t);
+ __u32 local_vlen = btf_vlen(local_t);
+ __u32 targ_vlen = btf_vlen(targ_t);
int i, err;
if (local_k != targ_k)
--
2.39.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 bpf-next 3/8] libbpf: Add feature for kernel extended vlen/kind support
2026-04-16 14:38 [PATCH v2 bpf-next 0/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
2026-04-16 14:38 ` [PATCH v2 bpf-next 1/8] " Alan Maguire
2026-04-16 14:38 ` [PATCH v2 bpf-next 2/8] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
@ 2026-04-16 14:38 ` Alan Maguire
2026-04-16 15:27 ` bot+bpf-ci
` (2 more replies)
2026-04-16 14:39 ` [PATCH v2 bpf-next 4/8] bpftool: Support 24-bit vlen Alan Maguire
` (4 subsequent siblings)
7 siblings, 3 replies; 21+ messages in thread
From: Alan Maguire @ 2026-04-16 14:38 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, Alan Maguire
Add feature check for kernel extended vlen/kind support, and reject
BTF that uses extended vlens/kinds if the kernel does not support
it. There is no reasonable path to generally sanitize such BTF.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
tools/lib/bpf/features.c | 43 +++++++++++++++++++++++++++++++++
tools/lib/bpf/libbpf.c | 17 ++++++++++++-
tools/lib/bpf/libbpf_internal.h | 2 ++
3 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
index 4f19a0d79b0c..f835931f4afe 100644
--- a/tools/lib/bpf/features.c
+++ b/tools/lib/bpf/features.c
@@ -615,6 +615,46 @@ static int probe_kern_btf_layout(int token_fd)
(char *)layout, token_fd));
}
+#define EXTEND_TYPE_LEN ((3 * sizeof(struct btf_type) + sizeof(__u32))/sizeof(__u32))
+#define EXTEND_VLEN 0x10000
+#define EXTEND_SECINFO_LEN (EXTEND_VLEN * sizeof(struct btf_var_secinfo)/sizeof(__u32))
+
+static int probe_kern_btf_vlen_kind_extended(int token_fd)
+{
+ static const char strs[] = "\0int\0foo\0bar";
+ __u32 types[EXTEND_TYPE_LEN] = {
+ /* int */
+ BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4),
+ /* var */
+ BTF_TYPE_ENC(5 /* "foo" */, BTF_INFO_ENC(BTF_KIND_VAR, 0, 0), 1),
+ /* datasec */
+ BTF_TYPE_ENC(9 /* "bar" */, BTF_INFO_ENC(BTF_KIND_DATASEC, EXTEND_VLEN, 0), 0),
+ };
+ struct btf_var_secinfo *s;
+ __u32 *types_data;
+ __u32 i;
+ int ret;
+
+ types_data = calloc(EXTEND_TYPE_LEN + EXTEND_SECINFO_LEN, sizeof(__u32));
+ if (!types_data)
+ return -ENOMEM;
+ memcpy(types_data, types, sizeof(types));
+
+ for (i = 0, s = (struct btf_var_secinfo *)&types_data[EXTEND_TYPE_LEN];
+ i < EXTEND_VLEN; i++, s++) {
+ s->type = 2;
+ s->offset = 4 * i;
+ s->size = 4;
+ }
+
+ ret = probe_fd(libbpf__load_raw_btf((char *)types_data,
+ (EXTEND_TYPE_LEN + EXTEND_SECINFO_LEN) * sizeof(__u32),
+ strs, sizeof(strs), token_fd));
+ free(types_data);
+
+ return ret;
+}
+
typedef int (*feature_probe_fn)(int /* token_fd */);
static struct kern_feature_cache feature_cache;
@@ -699,6 +739,9 @@ static struct kern_feature_desc {
[FEAT_BTF_LAYOUT] = {
"kernel supports BTF layout", probe_kern_btf_layout,
},
+ [FEAT_BTF_VLEN_KIND_EXTENDED] = {
+ "kernel supports extended BTF vlen/kind", probe_kern_btf_vlen_kind_extended,
+ },
};
bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_id)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 8b0c3246097f..5f19d8ac17a9 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -3139,10 +3139,11 @@ static bool btf_needs_sanitization(struct bpf_object *obj)
bool has_enum64 = kernel_supports(obj, FEAT_BTF_ENUM64);
bool has_qmark_datasec = kernel_supports(obj, FEAT_BTF_QMARK_DATASEC);
bool has_layout = kernel_supports(obj, FEAT_BTF_LAYOUT);
+ bool has_vlen_kind_extended = kernel_supports(obj, FEAT_BTF_VLEN_KIND_EXTENDED);
return !has_func || !has_datasec || !has_func_global || !has_float ||
!has_decl_tag || !has_type_tag || !has_enum64 || !has_qmark_datasec ||
- !has_layout;
+ !has_layout || !has_vlen_kind_extended;
}
struct btf *bpf_object__sanitize_btf(struct bpf_object *obj, struct btf *orig_btf)
@@ -3156,6 +3157,7 @@ struct btf *bpf_object__sanitize_btf(struct bpf_object *obj, struct btf *orig_bt
bool has_enum64 = kernel_supports(obj, FEAT_BTF_ENUM64);
bool has_qmark_datasec = kernel_supports(obj, FEAT_BTF_QMARK_DATASEC);
bool has_layout = kernel_supports(obj, FEAT_BTF_LAYOUT);
+ bool has_vlen_kind_extended = kernel_supports(obj, FEAT_BTF_VLEN_KIND_EXTENDED);
int enum64_placeholder_id = 0;
const struct btf_header *hdr;
struct btf *btf = NULL;
@@ -3217,6 +3219,19 @@ struct btf *bpf_object__sanitize_btf(struct bpf_object *obj, struct btf *orig_bt
for (i = 1; i < btf__type_cnt(btf); i++) {
t = (struct btf_type *)btf__type_by_id(btf, i);
+ /*
+ * If BTF uses extended vlen/kind and kernel does not support
+ * it, there is nothing we can do.
+ */
+ if (!has_vlen_kind_extended) {
+ if (btf_vlen(t) > 0xffff || btf_kind(t) > 0x1f) {
+ pr_debug("Unsupported %s for id %u\n",
+ btf_kind(t) > 0x1f ? "BTF kind" : "BTF vlen", i);
+ btf__free(btf);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
if ((!has_datasec && btf_is_var(t)) || (!has_decl_tag && btf_is_decl_tag(t))) {
/* replace VAR/DECL_TAG with INT */
t->info = BTF_INFO_ENC(BTF_KIND_INT, 0, 0);
diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
index 3781c45b46d3..9ca0796210d2 100644
--- a/tools/lib/bpf/libbpf_internal.h
+++ b/tools/lib/bpf/libbpf_internal.h
@@ -398,6 +398,8 @@ enum kern_feature_id {
FEAT_UPROBE_SYSCALL,
/* Kernel supports BTF layout information */
FEAT_BTF_LAYOUT,
+ /* Kernel supports BTF vlen > 65535, kind > 31 */
+ FEAT_BTF_VLEN_KIND_EXTENDED,
__FEAT_CNT,
};
--
2.39.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 bpf-next 4/8] bpftool: Support 24-bit vlen
2026-04-16 14:38 [PATCH v2 bpf-next 0/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
` (2 preceding siblings ...)
2026-04-16 14:38 ` [PATCH v2 bpf-next 3/8] libbpf: Add feature for kernel extended vlen/kind support Alan Maguire
@ 2026-04-16 14:39 ` Alan Maguire
2026-04-16 15:15 ` bot+bpf-ci
2026-04-16 14:39 ` [PATCH v2 bpf-next 5/8] selftests/bpf: Test BTF sanitization rejection for invalid vlen Alan Maguire
` (3 subsequent siblings)
7 siblings, 1 reply; 21+ messages in thread
From: Alan Maguire @ 2026-04-16 14:39 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, Alan Maguire
Adjust btf_vlen() usage to handle 24-bit vlen.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
tools/bpf/bpftool/btf.c | 17 ++++++-----------
tools/bpf/bpftool/btf_dumper.c | 4 ++--
tools/bpf/bpftool/gen.c | 16 +++++++++-------
3 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
index 2e899e940034..6ef908adf3a4 100644
--- a/tools/bpf/bpftool/btf.c
+++ b/tools/bpf/bpftool/btf.c
@@ -179,8 +179,7 @@ static int dump_btf_type(const struct btf *btf, __u32 id,
case BTF_KIND_STRUCT:
case BTF_KIND_UNION: {
const struct btf_member *m = (const void *)(t + 1);
- __u16 vlen = BTF_INFO_VLEN(t->info);
- int i;
+ __u32 i, vlen = BTF_INFO_VLEN(t->info);
if (json_output) {
jsonw_uint_field(w, "size", t->size);
@@ -225,9 +224,8 @@ static int dump_btf_type(const struct btf *btf, __u32 id,
}
case BTF_KIND_ENUM: {
const struct btf_enum *v = (const void *)(t + 1);
- __u16 vlen = BTF_INFO_VLEN(t->info);
+ __u32 i, vlen = BTF_INFO_VLEN(t->info);
const char *encoding;
- int i;
encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
if (json_output) {
@@ -263,9 +261,8 @@ static int dump_btf_type(const struct btf *btf, __u32 id,
}
case BTF_KIND_ENUM64: {
const struct btf_enum64 *v = btf_enum64(t);
- __u16 vlen = btf_vlen(t);
+ __u32 i, vlen = btf_vlen(t);
const char *encoding;
- int i;
encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
if (json_output) {
@@ -325,8 +322,7 @@ static int dump_btf_type(const struct btf *btf, __u32 id,
}
case BTF_KIND_FUNC_PROTO: {
const struct btf_param *p = (const void *)(t + 1);
- __u16 vlen = BTF_INFO_VLEN(t->info);
- int i;
+ __u32 i, vlen = BTF_INFO_VLEN(t->info);
if (json_output) {
jsonw_uint_field(w, "ret_type_id", t->type);
@@ -369,8 +365,7 @@ static int dump_btf_type(const struct btf *btf, __u32 id,
case BTF_KIND_DATASEC: {
const struct btf_var_secinfo *v = (const void *)(t + 1);
const struct btf_type *vt;
- __u16 vlen = BTF_INFO_VLEN(t->info);
- int i;
+ __u32 i, vlen = BTF_INFO_VLEN(t->info);
if (json_output) {
jsonw_uint_field(w, "size", t->size);
@@ -675,7 +670,7 @@ static __u64 btf_name_hasher(__u64 hash, const struct btf *btf, __u32 name_off)
static __u64 btf_type_disambig_hash(const struct btf *btf, __u32 id, bool include_members)
{
const struct btf_type *t = btf__type_by_id(btf, id);
- int i;
+ __u32 i;
size_t hash = 0;
hash = btf_name_hasher(hash, btf, t->name_off);
diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c
index def297e879f4..9dc8425b1789 100644
--- a/tools/bpf/bpftool/btf_dumper.c
+++ b/tools/bpf/bpftool/btf_dumper.c
@@ -150,7 +150,7 @@ static int btf_dumper_enum(const struct btf_dumper *d,
{
const struct btf_enum *enums = btf_enum(t);
__s64 value;
- __u16 i;
+ __u32 i;
switch (t->size) {
case 8:
@@ -189,7 +189,7 @@ static int btf_dumper_enum64(const struct btf_dumper *d,
const struct btf_enum64 *enums = btf_enum64(t);
__u32 val_lo32, val_hi32;
__u64 value;
- __u16 i;
+ __u32 i;
value = *(__u64 *)data;
val_lo32 = (__u32)value;
diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c
index 2f9e10752e28..def7497e39c9 100644
--- a/tools/bpf/bpftool/gen.c
+++ b/tools/bpf/bpftool/gen.c
@@ -2094,7 +2094,8 @@ btfgen_mark_type(struct btfgen_info *info, unsigned int type_id, bool follow_poi
struct btf_type *cloned_type;
struct btf_param *param;
struct btf_array *array;
- int err, i;
+ __u32 i;
+ int err;
if (type_id == 0)
return 0;
@@ -2229,7 +2230,8 @@ static int btfgen_mark_type_match(struct btfgen_info *info, __u32 type_id, bool
const struct btf_type *btf_type;
struct btf *btf = info->src_btf;
struct btf_type *cloned_type;
- int i, err;
+ int err;
+ __u32 i;
if (type_id == 0)
return 0;
@@ -2249,7 +2251,7 @@ static int btfgen_mark_type_match(struct btfgen_info *info, __u32 type_id, bool
case BTF_KIND_STRUCT:
case BTF_KIND_UNION: {
struct btf_member *m = btf_members(btf_type);
- __u16 vlen = btf_vlen(btf_type);
+ __u32 vlen = btf_vlen(btf_type);
if (behind_ptr)
break;
@@ -2286,7 +2288,7 @@ static int btfgen_mark_type_match(struct btfgen_info *info, __u32 type_id, bool
break;
}
case BTF_KIND_FUNC_PROTO: {
- __u16 vlen = btf_vlen(btf_type);
+ __u32 vlen = btf_vlen(btf_type);
struct btf_param *param;
/* mark ret type */
@@ -2492,8 +2494,9 @@ static struct btf *btfgen_get_btf(struct btfgen_info *info)
{
struct btf *btf_new = NULL;
unsigned int *ids = NULL;
- unsigned int i, n = btf__type_cnt(info->marked_btf);
+ unsigned int n = btf__type_cnt(info->marked_btf);
int err = 0;
+ __u32 i;
btf_new = btf__new_empty();
if (!btf_new) {
@@ -2523,8 +2526,7 @@ static struct btf *btfgen_get_btf(struct btfgen_info *info)
/* add members for struct and union */
if (btf_is_composite(type)) {
struct btf_member *cloned_m, *m;
- unsigned short vlen;
- int idx_src;
+ unsigned int vlen, idx_src;
name = btf__str_by_offset(info->src_btf, type->name_off);
--
2.39.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 bpf-next 5/8] selftests/bpf: Test BTF sanitization rejection for invalid vlen
2026-04-16 14:38 [PATCH v2 bpf-next 0/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
` (3 preceding siblings ...)
2026-04-16 14:39 ` [PATCH v2 bpf-next 4/8] bpftool: Support 24-bit vlen Alan Maguire
@ 2026-04-16 14:39 ` Alan Maguire
2026-04-16 15:27 ` bot+bpf-ci
2026-04-16 20:20 ` sashiko-bot
2026-04-16 14:39 ` [PATCH v2 bpf-next 6/8] selftests/bpf: Fix up btf/invalid test for extended kind Alan Maguire
` (2 subsequent siblings)
7 siblings, 2 replies; 21+ messages in thread
From: Alan Maguire @ 2026-04-16 14:39 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, Alan Maguire
For kernel that does not support extended vlen, BTF should be
rejected. Simulate non-support using feature cache and ensure
BTF with extended vlen DATASEC is rejected.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
.../selftests/bpf/prog_tests/btf_sanitize.c | 70 ++++++++++++++++++-
1 file changed, 69 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c b/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
index 652b51efafc2..1349fc7b34e9 100644
--- a/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
+++ b/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
@@ -40,7 +40,7 @@ static const struct layout_btf layout_btf = {
.strs = "\0int",
};
-void test_btf_sanitize_layout(void)
+static void test_btf_sanitize_layout(void)
{
struct btf *orig = NULL, *sanitized = NULL;
struct kern_feature_cache *cache = NULL;
@@ -95,3 +95,71 @@ void test_btf_sanitize_layout(void)
btf__free(sanitized);
btf__free(orig);
}
+
+static void test_btf_sanitize_extended(void)
+{
+ struct btf *btf = NULL, *sanitized = NULL;
+ struct kern_feature_cache *cache = NULL;
+ struct kfree_skb *skel = NULL;
+ int i;
+
+ skel = kfree_skb__open();
+ if (!ASSERT_OK_PTR(skel, "kfree_skb_skel"))
+ return;
+
+ if (!ASSERT_OK(kernel_supports(skel->obj, FEAT_BTF_VLEN_KIND_EXTENDED),
+ "vlen_kind_extended_supported"))
+ goto out;
+
+ cache = calloc(1, sizeof(*cache));
+ if (!ASSERT_OK_PTR(cache, "alloc_feat_cache"))
+ goto out;
+ for (i = 0; i < __FEAT_CNT; i++)
+ cache->res[i] = FEAT_SUPPORTED;
+ cache->res[FEAT_BTF_VLEN_KIND_EXTENDED] = FEAT_MISSING;
+
+ bpf_object_set_feat_cache(skel->obj, cache);
+
+ if (!ASSERT_FALSE(kernel_supports(skel->obj, FEAT_BTF_VLEN_KIND_EXTENDED),
+ "vlen_kind_extended_feature_missing"))
+ goto out;
+ if (!ASSERT_TRUE(kernel_supports(skel->obj, FEAT_BTF_FUNC), "other_feature_allowed"))
+ goto out;
+
+ btf = btf__new_empty();
+ if (!ASSERT_OK_PTR(btf, "empty_btf"))
+ goto out;
+ if (!ASSERT_GT(btf__add_int(btf, "int", 4, BTF_INT_SIGNED), 0, "add_int") ||
+ !ASSERT_GT(btf__add_var(btf, "var1", 0, 1), 0, "add_var") ||
+ !ASSERT_GT(btf__add_datasec(btf, "datasec1", 0x10000), 0, "add_datasec"))
+ goto out;
+
+ for (i = 0; i < 0x10000; i++) {
+ if (!ASSERT_OK(btf__add_datasec_var_info(btf, 2, i * 4, 4), "add_var_info"))
+ goto out;
+ }
+
+ /* Sanitization should fail here as vlen surpasses unextended limit. */
+ sanitized = bpf_object__sanitize_btf(skel->obj, btf);
+ if (!ASSERT_ERR_PTR(sanitized, "bpf_object__sanitize_btf_should_fail"))
+ goto out;
+
+ /* Now switch extended feature on and ensure success. */
+ cache->res[FEAT_BTF_VLEN_KIND_EXTENDED] = FEAT_SUPPORTED;
+ sanitized = bpf_object__sanitize_btf(skel->obj, btf);
+ ASSERT_OK_PTR(sanitized, "bpf_object__sanitize_btf_should_succeed");
+
+out:
+ /* This will free the cache we allocated above */
+ kfree_skb__destroy(skel);
+ btf__free(btf);
+ btf__free(sanitized);
+}
+
+void test_btf_sanitize(void)
+{
+ if (test__start_subtest("layout"))
+ test_btf_sanitize_layout();
+ if (test__start_subtest("extended"))
+ test_btf_sanitize_extended();
+}
--
2.39.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 bpf-next 6/8] selftests/bpf: Fix up btf/invalid test for extended kind
2026-04-16 14:38 [PATCH v2 bpf-next 0/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
` (4 preceding siblings ...)
2026-04-16 14:39 ` [PATCH v2 bpf-next 5/8] selftests/bpf: Test BTF sanitization rejection for invalid vlen Alan Maguire
@ 2026-04-16 14:39 ` Alan Maguire
2026-04-16 14:39 ` [PATCH v2 bpf-next 7/8] selftests/bpf: Fix up __u16 vlen assumptions Alan Maguire
2026-04-16 14:39 ` [PATCH v2 bpf-next 8/8] Documentation/bpf: Update btf doc with updated vlen, kind sizes Alan Maguire
7 siblings, 0 replies; 21+ messages in thread
From: Alan Maguire @ 2026-04-16 14:39 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, Alan Maguire
With extended kinds, 32 becomes a valid (but not used)
BTF info kind value; fix up the test to check for the
"Invalid kind" rather than "Invalid btf_info" message.
Since all bits are used in BTF info, it is no longer
possible to craft an invalid BTF info value. Use
127 (new maximum possible kind value).
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
tools/testing/selftests/bpf/prog_tests/btf.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/btf.c b/tools/testing/selftests/bpf/prog_tests/btf.c
index 054ecb6b1e9f..0cc347e32db3 100644
--- a/tools/testing/selftests/bpf/prog_tests/btf.c
+++ b/tools/testing/selftests/bpf/prog_tests/btf.c
@@ -1924,11 +1924,11 @@ static struct btf_raw_test raw_tests[] = {
},
{
- .descr = "invalid BTF_INFO",
+ .descr = "invalid BTF kind",
.raw_types = {
/* int */ /* [1] */
BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
- BTF_TYPE_ENC(0, 0x20000000, 4),
+ BTF_TYPE_ENC(0, 0x7f000000, 4),
BTF_END_RAW,
},
.str_sec = "",
@@ -1941,7 +1941,7 @@ static struct btf_raw_test raw_tests[] = {
.value_type_id = 1,
.max_entries = 4,
.btf_load_err = true,
- .err_str = "Invalid btf_info",
+ .err_str = "Invalid kind",
},
{
--
2.39.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 bpf-next 7/8] selftests/bpf: Fix up __u16 vlen assumptions
2026-04-16 14:38 [PATCH v2 bpf-next 0/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
` (5 preceding siblings ...)
2026-04-16 14:39 ` [PATCH v2 bpf-next 6/8] selftests/bpf: Fix up btf/invalid test for extended kind Alan Maguire
@ 2026-04-16 14:39 ` Alan Maguire
2026-04-16 20:32 ` sashiko-bot
2026-04-16 14:39 ` [PATCH v2 bpf-next 8/8] Documentation/bpf: Update btf doc with updated vlen, kind sizes Alan Maguire
7 siblings, 1 reply; 21+ messages in thread
From: Alan Maguire @ 2026-04-16 14:39 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, Alan Maguire
Fix up a few cases where we assume vlen is 16 bits.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
tools/testing/selftests/bpf/prog_tests/btf.c | 2 +-
tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c | 2 +-
tools/testing/selftests/bpf/test_progs.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/btf.c b/tools/testing/selftests/bpf/prog_tests/btf.c
index 0cc347e32db3..a9de328a8697 100644
--- a/tools/testing/selftests/bpf/prog_tests/btf.c
+++ b/tools/testing/selftests/bpf/prog_tests/btf.c
@@ -8092,7 +8092,7 @@ static struct btf_dedup_test dedup_tests[] = {
static int btf_type_size(const struct btf_type *t)
{
int base_size = sizeof(struct btf_type);
- __u16 vlen = BTF_INFO_VLEN(t->info);
+ __u32 vlen = BTF_INFO_VLEN(t->info);
__u16 kind = BTF_INFO_KIND(t->info);
switch (kind) {
diff --git a/tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c b/tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c
index 5bc15bb6b7ce..4517b03bbd1c 100644
--- a/tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c
+++ b/tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c
@@ -487,7 +487,7 @@ static void test_split_module(void)
for (i = 0; i < ARRAY_SIZE(mod_funcs); i++) {
const struct btf_param *p;
const struct btf_type *t;
- __u16 vlen;
+ __u32 vlen;
__u32 id;
int j;
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index 7fe16b5131b1..cc14b13e23fe 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -1257,7 +1257,7 @@ int get_bpf_max_tramp_links_from(struct btf *btf)
const struct btf_type *t;
__u32 i, type_cnt;
const char *name;
- __u16 j, vlen;
+ __u32 j, vlen;
for (i = 1, type_cnt = btf__type_cnt(btf); i < type_cnt; i++) {
t = btf__type_by_id(btf, i);
--
2.39.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH v2 bpf-next 8/8] Documentation/bpf: Update btf doc with updated vlen, kind sizes
2026-04-16 14:38 [PATCH v2 bpf-next 0/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
` (6 preceding siblings ...)
2026-04-16 14:39 ` [PATCH v2 bpf-next 7/8] selftests/bpf: Fix up __u16 vlen assumptions Alan Maguire
@ 2026-04-16 14:39 ` Alan Maguire
7 siblings, 0 replies; 21+ messages in thread
From: Alan Maguire @ 2026-04-16 14:39 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, Alan Maguire
Sync doc with updated UAPI changes utilizing unused bts for
extended vlen, kind values.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
Documentation/bpf/btf.rst | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/Documentation/bpf/btf.rst b/Documentation/bpf/btf.rst
index 3b60583f5db2..3f05f17990ad 100644
--- a/Documentation/bpf/btf.rst
+++ b/Documentation/bpf/btf.rst
@@ -97,10 +97,8 @@ Each type contains the following common data::
struct btf_type {
__u32 name_off;
/* "info" bits arrangement
- * bits 0-15: vlen (e.g. # of struct's members)
- * bits 16-23: unused
- * bits 24-28: kind (e.g. int, ptr, array...etc)
- * bits 29-30: unused
+ * bits 0-23: vlen (e.g. # of struct's members)
+ * bits 24-30: kind (e.g. int, ptr, array...etc)
* bit 31: kind_flag, currently used by
* struct, union, enum, fwd, enum64,
* decl_tag and type_tag
--
2.39.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH v2 bpf-next 4/8] bpftool: Support 24-bit vlen
2026-04-16 14:39 ` [PATCH v2 bpf-next 4/8] bpftool: Support 24-bit vlen Alan Maguire
@ 2026-04-16 15:15 ` bot+bpf-ci
0 siblings, 0 replies; 21+ messages in thread
From: bot+bpf-ci @ 2026-04-16 15:15 UTC (permalink / raw)
To: alan.maguire, ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, alan.maguire, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 875 bytes --]
> diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c
> --- a/tools/bpf/bpftool/gen.c
> +++ b/tools/bpf/bpftool/gen.c
[ ... ]
> @@ -2523,8 +2526,7 @@ static struct btf *btfgen_get_btf(struct btfgen_info *info)
> /* add members for struct and union */
> if (btf_is_composite(type)) {
> struct btf_member *cloned_m, *m;
> - unsigned short vlen;
> - int idx_src;
> + unsigned int vlen, idx_src;
This isn't a bug, but the rest of the patch consistently uses __u32 for
vlen (in btf.c dump_btf_type, and in btfgen_mark_type_match), while
this one spot uses unsigned int. Should this be __u32 for consistency?
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/24517220149
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 bpf-next 2/8] libbpf: Adjust btf_vlen() to return a __u32
2026-04-16 14:38 ` [PATCH v2 bpf-next 2/8] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
@ 2026-04-16 15:27 ` bot+bpf-ci
2026-04-16 19:36 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: bot+bpf-ci @ 2026-04-16 15:27 UTC (permalink / raw)
To: alan.maguire, ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, alan.maguire, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1891 bytes --]
> diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
> index ceb57b46a878..dfe72235e5dc 100644
> --- a/tools/lib/bpf/btf.c
> +++ b/tools/lib/bpf/btf.c
[ ... ]
> @@ -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;
> }
The overflow check was added here for btf_type_inc_vlen(), and its
four callers (btf__add_enum_value, btf__add_enum64_value,
btf__add_func_param, btf__add_datasec_var_info) were all updated to
check the return value.
However, btf__add_field() increments vlen inline without going through
btf_type_inc_vlen() and has no corresponding overflow check:
tools/lib/bpf/btf.c:btf__add_field() {
...
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));
...
}
If btf_vlen(t) reaches BTF_MAX_VLEN (0x00ffffff), the +1 produces
0x01000000. Since btf_type_info() does not mask the vlen argument:
tools/lib/bpf/libbpf_internal.h:btf_type_info() {
return (kflag << 31) | (kind << 24) | vlen;
}
bit 24 of the overflowed vlen bleeds into the kind field, silently
corrupting t->info. Should btf__add_field() get the same
BTF_MAX_VLEN overflow check that was added to btf_type_inc_vlen()?
This was not found to be fixed later in the series.
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/24517220149
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 bpf-next 5/8] selftests/bpf: Test BTF sanitization rejection for invalid vlen
2026-04-16 14:39 ` [PATCH v2 bpf-next 5/8] selftests/bpf: Test BTF sanitization rejection for invalid vlen Alan Maguire
@ 2026-04-16 15:27 ` bot+bpf-ci
2026-04-16 20:20 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: bot+bpf-ci @ 2026-04-16 15:27 UTC (permalink / raw)
To: alan.maguire, ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, alan.maguire, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1559 bytes --]
> diff --git a/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c b/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
> index 652b51efafc2..1349fc7b34e9 100644
> --- a/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
> +++ b/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
[ ... ]
> +static void test_btf_sanitize_extended(void)
> +{
[ ... ]
> + if (!ASSERT_OK(kernel_supports(skel->obj, FEAT_BTF_VLEN_KIND_EXTENDED),
> + "vlen_kind_extended_supported"))
> + goto out;
Should this be ASSERT_TRUE instead of ASSERT_OK? kernel_supports()
returns bool, and ASSERT_OK checks that its argument equals zero:
#define ASSERT_OK(res, name) ({
long long ___res = (res);
bool ___ok = ___res == 0;
...
})
When the kernel supports extended vlen, kernel_supports() returns
true (1), so ASSERT_OK sees a nonzero value and fails the assertion.
This causes the test to skip on kernels that do support the feature,
which is exactly where it needs to run.
The later assertions in the same function use the correct macros:
> + if (!ASSERT_FALSE(kernel_supports(skel->obj, FEAT_BTF_VLEN_KIND_EXTENDED),
> + "vlen_kind_extended_feature_missing"))
> + goto out;
> + if (!ASSERT_TRUE(kernel_supports(skel->obj, FEAT_BTF_FUNC), "other_feature_allowed"))
> + goto out;
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/24517220149
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 bpf-next 3/8] libbpf: Add feature for kernel extended vlen/kind support
2026-04-16 14:38 ` [PATCH v2 bpf-next 3/8] libbpf: Add feature for kernel extended vlen/kind support Alan Maguire
@ 2026-04-16 15:27 ` bot+bpf-ci
2026-04-16 15:56 ` Alexei Starovoitov
2026-04-16 20:01 ` sashiko-bot
2 siblings, 0 replies; 21+ messages in thread
From: bot+bpf-ci @ 2026-04-16 15:27 UTC (permalink / raw)
To: alan.maguire, ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf, alan.maguire, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2538 bytes --]
> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
> index 4f19a0d79b0c..f835931f4afe 100644
> --- a/tools/lib/bpf/features.c
> +++ b/tools/lib/bpf/features.c
[ ... ]
> +static int probe_kern_btf_vlen_kind_extended(int token_fd)
> +{
> + static const char strs[] = "\0int\0foo\0bar";
> + __u32 types[EXTEND_TYPE_LEN] = {
> + /* int */
> + BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4),
> + /* var */
> + BTF_TYPE_ENC(5 /* "foo" */, BTF_INFO_ENC(BTF_KIND_VAR, 0, 0), 1),
Is the btf_var linkage data missing here? BTF_KIND_VAR requires a
trailing struct btf_var (linkage value) after the btf_type. The
existing probe_kern_btf_datasec() in the same file includes
BTF_VAR_STATIC after the VAR type:
tools/lib/bpf/features.c:probe_kern_btf_datasec() {
...
BTF_TYPE_ENC(1, BTF_INFO_ENC(BTF_KIND_VAR, 0, 0), 1),
BTF_VAR_STATIC,
...
}
Without it, the kernel's btf_var_check_meta() reads into the next
type's data for the linkage value and rejects it. EXTEND_TYPE_LEN
would also need to account for the extra __u32.
> + /* datasec */
> + BTF_TYPE_ENC(9 /* "bar" */, BTF_INFO_ENC(BTF_KIND_DATASEC, EXTEND_VLEN, 0), 0),
Are the BTF_INFO_ENC arguments swapped here? The macro signature is:
BTF_INFO_ENC(kind, kind_flag, vlen)
This passes EXTEND_VLEN (0x10000) as kind_flag and 0 as vlen, which
produces kflag=1 and vlen=0. The kernel rejects kflag on DATASEC
types, and vlen=0 means the probe doesn't actually test extended vlen.
Comparing with probe_kern_btf_datasec() which uses the correct order:
BTF_INFO_ENC(BTF_KIND_DATASEC, 0, 1)
Should this be BTF_INFO_ENC(BTF_KIND_DATASEC, 0, EXTEND_VLEN)?
Additionally, the third argument to BTF_TYPE_ENC here is 0, which
sets the DATASEC size to 0. The kernel's btf_datasec_check_meta()
rejects size == 0. Should the size reflect the var_secinfo entries,
something like 4 * EXTEND_VLEN?
These three issues (missing btf_var, swapped BTF_INFO_ENC arguments,
and zero DATASEC size) each independently cause the kernel to reject
this BTF, so the probe always fails regardless of actual kernel
support. This means FEAT_BTF_VLEN_KIND_EXTENDED is never detected,
and bpf_object__sanitize_btf() will always reject BTF with extended
vlen or kind values even on kernels that support them.
> + };
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/24517220149
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 bpf-next 1/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits
2026-04-16 14:38 ` [PATCH v2 bpf-next 1/8] " Alan Maguire
@ 2026-04-16 15:54 ` Alexei Starovoitov
2026-04-16 19:05 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: Alexei Starovoitov @ 2026-04-16 15:54 UTC (permalink / raw)
To: Alan Maguire, ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf
On Thu Apr 16, 2026 at 7:38 AM PDT, Alan Maguire wrote:
> (not used) kind. Provide backwards-compatible macros just in
> case.
...
> +/*
> + * Macros needed for backwards compatibility; enum above ensures values
> + * make it into BTF.
> + */
> +#define BTF_MAX_TYPE BTF_MAX_TYPE
> +#define BTF_MAX_NAME_OFFSET BTF_MAX_NAME_OFFSET
> +#define BTF_MAX_VLEN BTF_MAX_VLEN
let's not. Ignore bots.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 bpf-next 3/8] libbpf: Add feature for kernel extended vlen/kind support
2026-04-16 14:38 ` [PATCH v2 bpf-next 3/8] libbpf: Add feature for kernel extended vlen/kind support Alan Maguire
2026-04-16 15:27 ` bot+bpf-ci
@ 2026-04-16 15:56 ` Alexei Starovoitov
2026-04-16 16:08 ` Alan Maguire
2026-04-16 20:01 ` sashiko-bot
2 siblings, 1 reply; 21+ messages in thread
From: Alexei Starovoitov @ 2026-04-16 15:56 UTC (permalink / raw)
To: Alan Maguire, ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf
On Thu Apr 16, 2026 at 7:38 AM PDT, Alan Maguire wrote:
> Add feature check for kernel extended vlen/kind support, and reject
> BTF that uses extended vlens/kinds if the kernel does not support
> it. There is no reasonable path to generally sanitize such BTF.
>
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> ---
> tools/lib/bpf/features.c | 43 +++++++++++++++++++++++++++++++++
> tools/lib/bpf/libbpf.c | 17 ++++++++++++-
> tools/lib/bpf/libbpf_internal.h | 2 ++
> 3 files changed, 61 insertions(+), 1 deletion(-)
>
> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
> index 4f19a0d79b0c..f835931f4afe 100644
> --- a/tools/lib/bpf/features.c
> +++ b/tools/lib/bpf/features.c
> @@ -615,6 +615,46 @@ static int probe_kern_btf_layout(int token_fd)
> (char *)layout, token_fd));
> }
>
> +#define EXTEND_TYPE_LEN ((3 * sizeof(struct btf_type) + sizeof(__u32))/sizeof(__u32))
> +#define EXTEND_VLEN 0x10000
> +#define EXTEND_SECINFO_LEN (EXTEND_VLEN * sizeof(struct btf_var_secinfo)/sizeof(__u32))
> +
> +static int probe_kern_btf_vlen_kind_extended(int token_fd)
> +{
> + static const char strs[] = "\0int\0foo\0bar";
> + __u32 types[EXTEND_TYPE_LEN] = {
> + /* int */
> + BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4),
> + /* var */
> + BTF_TYPE_ENC(5 /* "foo" */, BTF_INFO_ENC(BTF_KIND_VAR, 0, 0), 1),
> + /* datasec */
> + BTF_TYPE_ENC(9 /* "bar" */, BTF_INFO_ENC(BTF_KIND_DATASEC, EXTEND_VLEN, 0), 0),
> + };
> + struct btf_var_secinfo *s;
> + __u32 *types_data;
> + __u32 i;
> + int ret;
> +
> + types_data = calloc(EXTEND_TYPE_LEN + EXTEND_SECINFO_LEN, sizeof(__u32));
> + if (!types_data)
> + return -ENOMEM;
> + memcpy(types_data, types, sizeof(types));
> +
> + for (i = 0, s = (struct btf_var_secinfo *)&types_data[EXTEND_TYPE_LEN];
> + i < EXTEND_VLEN; i++, s++) {
> + s->type = 2;
> + s->offset = 4 * i;
> + s->size = 4;
> + }
> +
> + ret = probe_fd(libbpf__load_raw_btf((char *)types_data,
> + (EXTEND_TYPE_LEN + EXTEND_SECINFO_LEN) * sizeof(__u32),
> + strs, sizeof(strs), token_fd));
> + free(types_data);
> +
> + return ret;
> +}
> +
> typedef int (*feature_probe_fn)(int /* token_fd */);
>
> static struct kern_feature_cache feature_cache;
> @@ -699,6 +739,9 @@ static struct kern_feature_desc {
> [FEAT_BTF_LAYOUT] = {
> "kernel supports BTF layout", probe_kern_btf_layout,
> },
> + [FEAT_BTF_VLEN_KIND_EXTENDED] = {
> + "kernel supports extended BTF vlen/kind", probe_kern_btf_vlen_kind_extended,
> + },
> };
>
> bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_id)
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 8b0c3246097f..5f19d8ac17a9 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -3139,10 +3139,11 @@ static bool btf_needs_sanitization(struct bpf_object *obj)
> bool has_enum64 = kernel_supports(obj, FEAT_BTF_ENUM64);
> bool has_qmark_datasec = kernel_supports(obj, FEAT_BTF_QMARK_DATASEC);
> bool has_layout = kernel_supports(obj, FEAT_BTF_LAYOUT);
> + bool has_vlen_kind_extended = kernel_supports(obj, FEAT_BTF_VLEN_KIND_EXTENDED);
>
> return !has_func || !has_datasec || !has_func_global || !has_float ||
> !has_decl_tag || !has_type_tag || !has_enum64 || !has_qmark_datasec ||
> - !has_layout;
> + !has_layout || !has_vlen_kind_extended;
> }
>
> struct btf *bpf_object__sanitize_btf(struct bpf_object *obj, struct btf *orig_btf)
> @@ -3156,6 +3157,7 @@ struct btf *bpf_object__sanitize_btf(struct bpf_object *obj, struct btf *orig_bt
> bool has_enum64 = kernel_supports(obj, FEAT_BTF_ENUM64);
> bool has_qmark_datasec = kernel_supports(obj, FEAT_BTF_QMARK_DATASEC);
> bool has_layout = kernel_supports(obj, FEAT_BTF_LAYOUT);
> + bool has_vlen_kind_extended = kernel_supports(obj, FEAT_BTF_VLEN_KIND_EXTENDED);
> int enum64_placeholder_id = 0;
> const struct btf_header *hdr;
> struct btf *btf = NULL;
> @@ -3217,6 +3219,19 @@ struct btf *bpf_object__sanitize_btf(struct bpf_object *obj, struct btf *orig_bt
> for (i = 1; i < btf__type_cnt(btf); i++) {
> t = (struct btf_type *)btf__type_by_id(btf, i);
>
> + /*
> + * If BTF uses extended vlen/kind and kernel does not support
> + * it, there is nothing we can do.
> + */
> + if (!has_vlen_kind_extended) {
> + if (btf_vlen(t) > 0xffff || btf_kind(t) > 0x1f) {
> + pr_debug("Unsupported %s for id %u\n",
> + btf_kind(t) > 0x1f ? "BTF kind" : "BTF vlen", i);
> + btf__free(btf);
> + return ERR_PTR(-EINVAL);
> + }
> + }
What's the point of the patch?
Just to make libbpf error early?
It seems it can be dropped. The kernel will error if it's old.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 bpf-next 3/8] libbpf: Add feature for kernel extended vlen/kind support
2026-04-16 15:56 ` Alexei Starovoitov
@ 2026-04-16 16:08 ` Alan Maguire
0 siblings, 0 replies; 21+ messages in thread
From: Alan Maguire @ 2026-04-16 16:08 UTC (permalink / raw)
To: Alexei Starovoitov, ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo,
mykyta.yatsenko5, bpf
On 16/04/2026 16:56, Alexei Starovoitov wrote:
> On Thu Apr 16, 2026 at 7:38 AM PDT, Alan Maguire wrote:
>> Add feature check for kernel extended vlen/kind support, and reject
>> BTF that uses extended vlens/kinds if the kernel does not support
>> it. There is no reasonable path to generally sanitize such BTF.
>>
>> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
>> ---
>> tools/lib/bpf/features.c | 43 +++++++++++++++++++++++++++++++++
>> tools/lib/bpf/libbpf.c | 17 ++++++++++++-
>> tools/lib/bpf/libbpf_internal.h | 2 ++
>> 3 files changed, 61 insertions(+), 1 deletion(-)
>>
>> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
>> index 4f19a0d79b0c..f835931f4afe 100644
>> --- a/tools/lib/bpf/features.c
>> +++ b/tools/lib/bpf/features.c
>> @@ -615,6 +615,46 @@ static int probe_kern_btf_layout(int token_fd)
>> (char *)layout, token_fd));
>> }
>>
>> +#define EXTEND_TYPE_LEN ((3 * sizeof(struct btf_type) + sizeof(__u32))/sizeof(__u32))
>> +#define EXTEND_VLEN 0x10000
>> +#define EXTEND_SECINFO_LEN (EXTEND_VLEN * sizeof(struct btf_var_secinfo)/sizeof(__u32))
>> +
>> +static int probe_kern_btf_vlen_kind_extended(int token_fd)
>> +{
>> + static const char strs[] = "\0int\0foo\0bar";
>> + __u32 types[EXTEND_TYPE_LEN] = {
>> + /* int */
>> + BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4),
>> + /* var */
>> + BTF_TYPE_ENC(5 /* "foo" */, BTF_INFO_ENC(BTF_KIND_VAR, 0, 0), 1),
>> + /* datasec */
>> + BTF_TYPE_ENC(9 /* "bar" */, BTF_INFO_ENC(BTF_KIND_DATASEC, EXTEND_VLEN, 0), 0),
>> + };
>> + struct btf_var_secinfo *s;
>> + __u32 *types_data;
>> + __u32 i;
>> + int ret;
>> +
>> + types_data = calloc(EXTEND_TYPE_LEN + EXTEND_SECINFO_LEN, sizeof(__u32));
>> + if (!types_data)
>> + return -ENOMEM;
>> + memcpy(types_data, types, sizeof(types));
>> +
>> + for (i = 0, s = (struct btf_var_secinfo *)&types_data[EXTEND_TYPE_LEN];
>> + i < EXTEND_VLEN; i++, s++) {
>> + s->type = 2;
>> + s->offset = 4 * i;
>> + s->size = 4;
>> + }
>> +
>> + ret = probe_fd(libbpf__load_raw_btf((char *)types_data,
>> + (EXTEND_TYPE_LEN + EXTEND_SECINFO_LEN) * sizeof(__u32),
>> + strs, sizeof(strs), token_fd));
>> + free(types_data);
>> +
>> + return ret;
>> +}
>> +
>> typedef int (*feature_probe_fn)(int /* token_fd */);
>>
>> static struct kern_feature_cache feature_cache;
>> @@ -699,6 +739,9 @@ static struct kern_feature_desc {
>> [FEAT_BTF_LAYOUT] = {
>> "kernel supports BTF layout", probe_kern_btf_layout,
>> },
>> + [FEAT_BTF_VLEN_KIND_EXTENDED] = {
>> + "kernel supports extended BTF vlen/kind", probe_kern_btf_vlen_kind_extended,
>> + },
>> };
>>
>> bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_id)
>> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
>> index 8b0c3246097f..5f19d8ac17a9 100644
>> --- a/tools/lib/bpf/libbpf.c
>> +++ b/tools/lib/bpf/libbpf.c
>> @@ -3139,10 +3139,11 @@ static bool btf_needs_sanitization(struct bpf_object *obj)
>> bool has_enum64 = kernel_supports(obj, FEAT_BTF_ENUM64);
>> bool has_qmark_datasec = kernel_supports(obj, FEAT_BTF_QMARK_DATASEC);
>> bool has_layout = kernel_supports(obj, FEAT_BTF_LAYOUT);
>> + bool has_vlen_kind_extended = kernel_supports(obj, FEAT_BTF_VLEN_KIND_EXTENDED);
>>
>> return !has_func || !has_datasec || !has_func_global || !has_float ||
>> !has_decl_tag || !has_type_tag || !has_enum64 || !has_qmark_datasec ||
>> - !has_layout;
>> + !has_layout || !has_vlen_kind_extended;
>> }
>>
>> struct btf *bpf_object__sanitize_btf(struct bpf_object *obj, struct btf *orig_btf)
>> @@ -3156,6 +3157,7 @@ struct btf *bpf_object__sanitize_btf(struct bpf_object *obj, struct btf *orig_bt
>> bool has_enum64 = kernel_supports(obj, FEAT_BTF_ENUM64);
>> bool has_qmark_datasec = kernel_supports(obj, FEAT_BTF_QMARK_DATASEC);
>> bool has_layout = kernel_supports(obj, FEAT_BTF_LAYOUT);
>> + bool has_vlen_kind_extended = kernel_supports(obj, FEAT_BTF_VLEN_KIND_EXTENDED);
>> int enum64_placeholder_id = 0;
>> const struct btf_header *hdr;
>> struct btf *btf = NULL;
>> @@ -3217,6 +3219,19 @@ struct btf *bpf_object__sanitize_btf(struct bpf_object *obj, struct btf *orig_bt
>> for (i = 1; i < btf__type_cnt(btf); i++) {
>> t = (struct btf_type *)btf__type_by_id(btf, i);
>>
>> + /*
>> + * If BTF uses extended vlen/kind and kernel does not support
>> + * it, there is nothing we can do.
>> + */
>> + if (!has_vlen_kind_extended) {
>> + if (btf_vlen(t) > 0xffff || btf_kind(t) > 0x1f) {
>> + pr_debug("Unsupported %s for id %u\n",
>> + btf_kind(t) > 0x1f ? "BTF kind" : "BTF vlen", i);
>> + btf__free(btf);
>> + return ERR_PTR(-EINVAL);
>> + }
>> + }
>
> What's the point of the patch?
> Just to make libbpf error early?
> It seems it can be dropped. The kernel will error if it's old.
Yeah, I guess the BTF_INFO_MASK test in btf_check_meta() will catch extended vlen/kind use
for older kernels, and it's been there since 2018. Can be dropped alright.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 bpf-next 1/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits
2026-04-16 14:38 ` [PATCH v2 bpf-next 1/8] " Alan Maguire
2026-04-16 15:54 ` Alexei Starovoitov
@ 2026-04-16 19:05 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-04-16 19:05 UTC (permalink / raw)
To: Alan Maguire; +Cc: bpf
Sashiko AI review found 1 potential issue(s):
- [High] UAPI C preprocessor breakage: Converting `BTF_MAX_*` constants to self-referential macros breaks existing `#if` evaluations in userspace.
--
commit ba6ded5102d9dc62d6101147f738a8a12d499303
Author: Alan Maguire <alan.maguire@oracle.com>
bpf: Extend BTF UAPI vlen, kinds to use unused bits
This commit extends BTF maximum vlen from 16 to 24 bits and kinds from
5 to 7 bits to support upcoming BTF location information. It converts the
BTF_MAX_* macros to an enum so they are encoded in kernel BTF, leaving
self-referential macros for backward compatibility.
Link: https://lore.kernel.org/bpf/CAEf4BzZx=X6vGqcA8SPU6D+v6k+TR=ZewebXMuXtpmML058piw@mail.gmail.com/
> diff --git a/include/uapi/linux/btf.h b/include/uapi/linux/btf.h
> --- a/include/uapi/linux/btf.h
> +++ b/include/uapi/linux/btf.h
[ ... ]
> +enum btf_max {
> + /* Max possible kind */
> + BTF_MAX_KIND = 0x0000007f,
> + /* Max # of type identifier */
> + BTF_MAX_TYPE = 0x000fffff,
> + /* Max offset into the string section */
> + BTF_MAX_NAME_OFFSET = 0x00ffffff,
> + /* Max # of struct/union/enum members or func args */
> + BTF_MAX_VLEN = 0x00ffffff,
> +};
> +
> +/*
> + * Macros needed for backwards compatibility; enum above ensures values
> + * make it into BTF.
> + */
> +#define BTF_MAX_TYPE BTF_MAX_TYPE
> +#define BTF_MAX_NAME_OFFSET BTF_MAX_NAME_OFFSET
> +#define BTF_MAX_VLEN BTF_MAX_VLEN
Will these self-referential macros break existing C preprocessor logic in
userspace?
While #ifdef BTF_MAX_VLEN will still evaluate to true, the preprocessor
does not have visibility into enum values. When evaluating #if directives
like #if BTF_MAX_VLEN == 0xffff, the macro expands to the identifier
BTF_MAX_VLEN, which is treated as an undefined symbol and evaluates to 0.
This means the check silently evaluates to false, which might break
build-time feature detection for userspace programs depending on this header.
Could these macros be defined to their exact integer literals after the enum
block instead?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260416143904.1220662-1-alan.maguire@oracle.com?part=1
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 bpf-next 2/8] libbpf: Adjust btf_vlen() to return a __u32
2026-04-16 14:38 ` [PATCH v2 bpf-next 2/8] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
2026-04-16 15:27 ` bot+bpf-ci
@ 2026-04-16 19:36 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-04-16 19:36 UTC (permalink / raw)
To: Alan Maguire; +Cc: bpf
Sashiko AI review found 1 potential issue(s):
- [High] btf__add_field() manually increments vlen without checking for BTF_MAX_VLEN overflow, leading to silent BTF type corruption.
--
commit bc2a5650478dca79064a34b0022bfd5fa6e2da77
Author: Alan Maguire <alan.maguire@oracle.com>
libbpf: Adjust btf_vlen() to return a __u32
Now that vlen is 24 bits, btf_vlen() must return a __u32.
Adjust use cases in libbpf accordingly. Also add error
handling to avoid vlen overflow in btf_type_inc_vlen().
> diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
> --- a/tools/lib/bpf/btf.c
> +++ b/tools/lib/bpf/btf.c
[ ... ]
> @@ -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;
> }
Does btf__add_field() also need to check for BTF_MAX_VLEN overflow?
It looks like btf__add_field() manually increments the length without using
btf_type_inc_vlen() to preserve the kflag:
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));
If a struct or union exceeds the maximum number of members, could this
increment overflow into the kind bits and corrupt the BTF type boundaries?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260416143904.1220662-1-alan.maguire@oracle.com?part=2
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 bpf-next 3/8] libbpf: Add feature for kernel extended vlen/kind support
2026-04-16 14:38 ` [PATCH v2 bpf-next 3/8] libbpf: Add feature for kernel extended vlen/kind support Alan Maguire
2026-04-16 15:27 ` bot+bpf-ci
2026-04-16 15:56 ` Alexei Starovoitov
@ 2026-04-16 20:01 ` sashiko-bot
2 siblings, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-04-16 20:01 UTC (permalink / raw)
To: Alan Maguire; +Cc: bpf
Sashiko AI review found 1 potential issue(s):
- [High] Feature probe `probe_kern_btf_vlen_kind_extended` is malformed and always fails, breaking extended BTF support.
--
commit 45c7cfd438137b97d67612513eb9d60104376b8f
Author: Alan Maguire <alan.maguire@oracle.com>
libbpf: Add feature for kernel extended vlen/kind support
This commit adds a feature check for kernel extended vlen/kind support, and
rejects BTF that uses extended vlens/kinds if the kernel does not support it.
> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
> index 4f19a0d79b0cf..f835931f4afe7 100644
> --- a/tools/lib/bpf/features.c
> +++ b/tools/lib/bpf/features.c
[ ... ]
> +static int probe_kern_btf_vlen_kind_extended(int token_fd)
> +{
> + static const char strs[] = "\0int\0foo\0bar";
> + __u32 types[EXTEND_TYPE_LEN] = {
> + /* int */
> + BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4),
> + /* var */
> + BTF_TYPE_ENC(5 /* "foo" */, BTF_INFO_ENC(BTF_KIND_VAR, 0, 0), 1),
Is this BTF_KIND_VAR type missing its required trailing struct btf_var
payload? Without it, the kernel's BTF parser might become misaligned
and reject the entire raw BTF payload.
> + /* datasec */
> + BTF_TYPE_ENC(9 /* "bar" */, BTF_INFO_ENC(BTF_KIND_DATASEC, EXTEND_VLEN, 0), 0),
Looking at BTF_INFO_ENC(kind, kflag, vlen), it appears EXTEND_VLEN is being
passed as the kflag argument rather than vlen. This leaves vlen as 0 and
sets the kflag bit. Could the kernel's btf_datasec_check_meta() reject this?
Additionally, the size argument to BTF_TYPE_ENC here is 0. Will the kernel
reject this DATASEC type since a zero size usually returns -EINVAL?
Finally, if vlen evaluates to 0, will the appended EXTEND_VLEN
btf_var_secinfo structures below be parsed by the kernel as independent
trailing BTF types? If the first struct evaluates to BTF_KIND_UNKN, the
entire probe might fail unconditionally.
> + };
> + struct btf_var_secinfo *s;
> + __u32 *types_data;
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260416143904.1220662-1-alan.maguire@oracle.com?part=3
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 bpf-next 5/8] selftests/bpf: Test BTF sanitization rejection for invalid vlen
2026-04-16 14:39 ` [PATCH v2 bpf-next 5/8] selftests/bpf: Test BTF sanitization rejection for invalid vlen Alan Maguire
2026-04-16 15:27 ` bot+bpf-ci
@ 2026-04-16 20:20 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-04-16 20:20 UTC (permalink / raw)
To: Alan Maguire; +Cc: bpf
Sashiko AI review found 2 potential issue(s):
- [High] Incorrect assertion macro `ASSERT_OK` used for boolean return value `kernel_supports()`, leading to spurious test failures on kernels supporting the feature.
- [Medium] Malformed BTF construction: DATASEC byte size is too small for the added variables, resulting in out-of-bounds offsets.
--
commit 547d5170cb3d8f555e19115439d037e23963de75
Author: Alan Maguire <alan.maguire@oracle.com>
selftests/bpf: Test BTF sanitization rejection for invalid vlen
For a kernel that does not support extended vlen, BTF should be
rejected. This commit simulates non-support using the feature cache
and ensures that BTF with an extended vlen DATASEC is rejected.
> diff --git a/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c b/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
> index 652b51efafc27..1349fc7b34e9c 100644
> --- a/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
> +++ b/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
[ ... ]
> +static void test_btf_sanitize_extended(void)
> +{
> + struct btf *btf = NULL, *sanitized = NULL;
> + struct kern_feature_cache *cache = NULL;
> + struct kfree_skb *skel = NULL;
> + int i;
> +
> + skel = kfree_skb__open();
> + if (!ASSERT_OK_PTR(skel, "kfree_skb_skel"))
> + return;
> +
> + if (!ASSERT_OK(kernel_supports(skel->obj, FEAT_BTF_VLEN_KIND_EXTENDED),
> + "vlen_kind_extended_supported"))
> + goto out;
Is ASSERT_OK the right macro to use for this check?
Because kernel_supports() returns a boolean, if the test is run on a kernel
that natively supports the feature, it will return true (1). Since ASSERT_OK
expects exactly 0 for success, this evaluates to ASSERT_OK(1) and triggers
a spurious test failure.
Would ASSERT_TRUE be more appropriate here to avoid aborting the test on
modern kernels?
> +
> + cache = calloc(1, sizeof(*cache));
[ ... ]
> + btf = btf__new_empty();
> + if (!ASSERT_OK_PTR(btf, "empty_btf"))
> + goto out;
> + if (!ASSERT_GT(btf__add_int(btf, "int", 4, BTF_INT_SIGNED), 0, "add_int") ||
> + !ASSERT_GT(btf__add_var(btf, "var1", 0, 1), 0, "add_var") ||
> + !ASSERT_GT(btf__add_datasec(btf, "datasec1", 0x10000), 0, "add_datasec"))
> + goto out;
> +
> + for (i = 0; i < 0x10000; i++) {
> + if (!ASSERT_OK(btf__add_datasec_var_info(btf, 2, i * 4, 4), "add_var_info"))
> + goto out;
> + }
Does this loop create a structurally malformed BTF object?
The DATASEC byte size is explicitly set to 0x10000 bytes above, but the loop
adds 0x10000 variables of size 4 at offsets up to 65535 * 4 (262140). This
places the variables far outside the declared bounds of the section.
Should the declared DATASEC size be 0x40000 instead to properly accommodate
the added variables and prevent unexpected failures if tighter bounds checks
are introduced?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260416143904.1220662-1-alan.maguire@oracle.com?part=5
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH v2 bpf-next 7/8] selftests/bpf: Fix up __u16 vlen assumptions
2026-04-16 14:39 ` [PATCH v2 bpf-next 7/8] selftests/bpf: Fix up __u16 vlen assumptions Alan Maguire
@ 2026-04-16 20:32 ` sashiko-bot
0 siblings, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-04-16 20:32 UTC (permalink / raw)
To: Alan Maguire; +Cc: bpf
Sashiko AI review found 1 potential issue(s):
- [Medium] The patch fails to fix the 16-bit assumption for `vlen` in `tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c`.
--
commit 033bc70f770dbba15f69901f422f7378dd7cd70e
Author: Alan Maguire <alan.maguire@oracle.com>
selftests/bpf: Fix up __u16 vlen assumptions
Fix up a few cases where we assume vlen is 16 bits.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> diff --git a/tools/testing/selftests/bpf/prog_tests/btf.c b/tools/testing/selftests/bpf/prog_tests/btf.c
> index 0cc347e32db37..a9de328a86976 100644
> --- a/tools/testing/selftests/bpf/prog_tests/btf.c
> +++ b/tools/testing/selftests/bpf/prog_tests/btf.c
> @@ -8092,7 +8092,7 @@ static struct btf_dedup_test dedup_tests[] = {
> static int btf_type_size(const struct btf_type *t)
> {
> int base_size = sizeof(struct btf_type);
> - __u16 vlen = BTF_INFO_VLEN(t->info);
> + __u32 vlen = BTF_INFO_VLEN(t->info);
> __u16 kind = BTF_INFO_KIND(t->info);
Does tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c also need to be
updated to handle 24-bit vlen values?
Looking at find_field_offset_aux(), mnum is still declared as __u16 and
assigned the result of btf_vlen():
tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c:find_field_offset_aux() {
const struct btf_type *type = btf__type_by_id(btf, btf_id);
const struct btf_member *m;
__u16 mnum;
int i;
...
m = btf_members(type);
mnum = btf_vlen(type);
for (i = 0; i < mnum; ++i, ++m) {
...
}
If a structure or union has more than 65,535 members, could mnum be
truncated here, causing the loop to terminate prematurely and failing to
resolve field offsets?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260416143904.1220662-1-alan.maguire@oracle.com?part=7
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2026-04-16 20:32 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-16 14:38 [PATCH v2 bpf-next 0/8] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
2026-04-16 14:38 ` [PATCH v2 bpf-next 1/8] " Alan Maguire
2026-04-16 15:54 ` Alexei Starovoitov
2026-04-16 19:05 ` sashiko-bot
2026-04-16 14:38 ` [PATCH v2 bpf-next 2/8] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
2026-04-16 15:27 ` bot+bpf-ci
2026-04-16 19:36 ` sashiko-bot
2026-04-16 14:38 ` [PATCH v2 bpf-next 3/8] libbpf: Add feature for kernel extended vlen/kind support Alan Maguire
2026-04-16 15:27 ` bot+bpf-ci
2026-04-16 15:56 ` Alexei Starovoitov
2026-04-16 16:08 ` Alan Maguire
2026-04-16 20:01 ` sashiko-bot
2026-04-16 14:39 ` [PATCH v2 bpf-next 4/8] bpftool: Support 24-bit vlen Alan Maguire
2026-04-16 15:15 ` bot+bpf-ci
2026-04-16 14:39 ` [PATCH v2 bpf-next 5/8] selftests/bpf: Test BTF sanitization rejection for invalid vlen Alan Maguire
2026-04-16 15:27 ` bot+bpf-ci
2026-04-16 20:20 ` sashiko-bot
2026-04-16 14:39 ` [PATCH v2 bpf-next 6/8] selftests/bpf: Fix up btf/invalid test for extended kind Alan Maguire
2026-04-16 14:39 ` [PATCH v2 bpf-next 7/8] selftests/bpf: Fix up __u16 vlen assumptions Alan Maguire
2026-04-16 20:32 ` sashiko-bot
2026-04-16 14:39 ` [PATCH v2 bpf-next 8/8] Documentation/bpf: Update btf doc with updated vlen, kind sizes Alan Maguire
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox