* [PATCH bpf-next 1/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits
2026-04-14 19:50 [PATCH bpf-next 0/6] btf: Extend vlen, kind in struct btf_type Alan Maguire
@ 2026-04-14 19:50 ` Alan Maguire
2026-04-14 20:42 ` bot+bpf-ci
2026-04-14 21:11 ` sashiko-bot
2026-04-14 19:50 ` [PATCH bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
` (4 subsequent siblings)
5 siblings, 2 replies; 21+ messages in thread
From: Alan Maguire @ 2026-04-14 19:50 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, 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.
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 | 26 ++++++++++++++------------
kernel/bpf/btf.c | 25 +++++++++----------------
tools/include/uapi/linux/btf.h | 26 ++++++++++++++------------
4 files changed, 39 insertions(+), 42 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..618167cab4e6 100644
--- a/include/uapi/linux/btf.h
+++ b/include/uapi/linux/btf.h
@@ -33,20 +33,22 @@ 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,
+};
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 +67,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..1663970fc1bf 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 {
@@ -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..618167cab4e6 100644
--- a/tools/include/uapi/linux/btf.h
+++ b/tools/include/uapi/linux/btf.h
@@ -33,20 +33,22 @@ 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,
+};
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 +67,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* Re: [PATCH bpf-next 1/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits
2026-04-14 19:50 ` [PATCH bpf-next 1/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
@ 2026-04-14 20:42 ` bot+bpf-ci
2026-04-14 21:11 ` sashiko-bot
1 sibling, 0 replies; 21+ messages in thread
From: bot+bpf-ci @ 2026-04-14 20:42 UTC (permalink / raw)
To: alan.maguire, ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, bpf,
alan.maguire, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1192 bytes --]
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index a62d78581207..1663970fc1bf 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
[ ... ]
> @@ -289,7 +288,7 @@ enum verifier_phase {
> struct resolve_vertex {
> const struct btf_type *t;
> u32 type_id;
> - u16 next_member;
> + u32 next_member;
> };
The next_member field is widened to u32 here, but
env_stack_set_next_member() still takes a u16 parameter:
static void env_stack_set_next_member(struct btf_verifier_env *env,
u16 next_member)
{
env->stack[env->top_stack - 1].next_member = next_member;
}
Both callers, btf_struct_resolve() and btf_datasec_resolve(), now use
u32 loop iterators and pass i + 1 to this function. For vlen values
above 65535, the u16 parameter would silently truncate the index,
causing the resolve loop to resume at the wrong member.
Should the next_member parameter be u32 to match the struct field?
---
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/24420385267
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH bpf-next 1/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits
2026-04-14 19:50 ` [PATCH bpf-next 1/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
2026-04-14 20:42 ` bot+bpf-ci
@ 2026-04-14 21:11 ` sashiko-bot
2026-04-15 15:48 ` Mykyta Yatsenko
1 sibling, 1 reply; 21+ messages in thread
From: sashiko-bot @ 2026-04-14 21:11 UTC (permalink / raw)
To: Alan Maguire; +Cc: bpf
Sashiko AI review found 2 potential issue(s):
- [High] The `env_stack_set_next_member()` helper takes a `u16` argument, which truncates the new 24-bit BTF `vlen` and causes an O(N^2) infinite-loop-like CPU lockup (Denial of Service).
- [Medium] UAPI Source Breakage: Converting `BTF_MAX_*` macros to `enum btf_max` removes preprocessor macros, breaking existing userspace compilation.
--
commit d88c0688f1be53ae1871dacf198a4a18b2e56ae0
Author: Alan Maguire <alan.maguire@oracle.com>
bpf: Extend BTF UAPI vlen, kinds to use unused bits
This commit expands the BTF maximum vlen from 16 bits to 24 bits, allowing
up to 16 million members. It also extends the BTF kind encoding from 5 to 7
bits, and converts the BTF_MAX_* constants to an enum to expose them in
kernel BTF.
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
> index 638615ebddc22..618167cab4e61 100644
> --- a/include/uapi/linux/btf.h
> +++ b/include/uapi/linux/btf.h
> @@ -33,20 +33,22 @@ 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,
> +};
Could replacing these #define macros with an enum break existing userspace
applications?
Programs using #ifdef BTF_MAX_VLEN or evaluating #if BTF_MAX_VLEN == ...
for conditional compilation will fail to build without the preprocessor
macros.
Would it be better to redefine the macros alongside the enums
(e.g., #define BTF_MAX_VLEN BTF_MAX_VLEN) to maintain UAPI backward
compatibility while still exposing the constants to BTF?
[ ... ]
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index a62d785812076..1663970fc1bf6 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -289,7 +288,7 @@ enum verifier_phase {
> struct resolve_vertex {
> const struct btf_type *t;
> u32 type_id;
> - u16 next_member;
> + u32 next_member;
> };
Does the env_stack_set_next_member() helper also need its next_member
argument updated to u32?
Looking at env_stack_set_next_member() in kernel/bpf/btf.c:
static void env_stack_set_next_member(struct btf_verifier_env *env,
u16 next_member)
{
env->stack[env->top_stack - 1].next_member = next_member;
}
Since the argument is still u16, won't this silently truncate the i + 1
index for any struct or datasec member beyond 65,535?
If this happens, when the verifier resumes resolution of the struct, could
it restart from the truncated index and redundantly iterate over
already-resolved members? With a very large number of members, could this
cause excessive CPU usage or soft lockups?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260414195019.684531-1-alan.maguire@oracle.com?part=1
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH bpf-next 1/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits
2026-04-14 21:11 ` sashiko-bot
@ 2026-04-15 15:48 ` Mykyta Yatsenko
0 siblings, 0 replies; 21+ messages in thread
From: Mykyta Yatsenko @ 2026-04-15 15:48 UTC (permalink / raw)
To: sashiko, Alan Maguire; +Cc: bpf
On 4/14/26 10:11 PM, sashiko-bot@kernel.org wrote:
> Sashiko AI review found 2 potential issue(s):
> - [High] The `env_stack_set_next_member()` helper takes a `u16` argument, which truncates the new 24-bit BTF `vlen` and causes an O(N^2) infinite-loop-like CPU lockup (Denial of Service).
> - [Medium] UAPI Source Breakage: Converting `BTF_MAX_*` macros to `enum btf_max` removes preprocessor macros, breaking existing userspace compilation.
> --
>
> commit d88c0688f1be53ae1871dacf198a4a18b2e56ae0
> Author: Alan Maguire <alan.maguire@oracle.com>
>
> bpf: Extend BTF UAPI vlen, kinds to use unused bits
>
> This commit expands the BTF maximum vlen from 16 bits to 24 bits, allowing
> up to 16 million members. It also extends the BTF kind encoding from 5 to 7
> bits, and converts the BTF_MAX_* constants to an enum to expose them in
> kernel BTF.
>
> 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
>> index 638615ebddc22..618167cab4e61 100644
>> --- a/include/uapi/linux/btf.h
>> +++ b/include/uapi/linux/btf.h
>> @@ -33,20 +33,22 @@ 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,
>> +};
>
> Could replacing these #define macros with an enum break existing userspace
> applications?
>
> Programs using #ifdef BTF_MAX_VLEN or evaluating #if BTF_MAX_VLEN == ...
> for conditional compilation will fail to build without the preprocessor
> macros.
>
> Would it be better to redefine the macros alongside the enums
> (e.g., #define BTF_MAX_VLEN BTF_MAX_VLEN) to maintain UAPI backward
> compatibility while still exposing the constants to BTF?
>
Looks like this is done on purpose and we don't expect anyone actually
use #ifdef BTF_MAX_VLEN, so it's an acceptable change.
> [ ... ]
>
>> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
>> index a62d785812076..1663970fc1bf6 100644
>> --- a/kernel/bpf/btf.c
>> +++ b/kernel/bpf/btf.c
>> @@ -289,7 +288,7 @@ enum verifier_phase {
>> struct resolve_vertex {
>> const struct btf_type *t;
>> u32 type_id;
>> - u16 next_member;
>> + u32 next_member;
>> };
>
> Does the env_stack_set_next_member() helper also need its next_member
> argument updated to u32?
>
> Looking at env_stack_set_next_member() in kernel/bpf/btf.c:
>
> static void env_stack_set_next_member(struct btf_verifier_env *env,
> u16 next_member)
> {
> env->stack[env->top_stack - 1].next_member = next_member;
> }
>
> Since the argument is still u16, won't this silently truncate the i + 1
> index for any struct or datasec member beyond 65,535?
>
> If this happens, when the verifier resumes resolution of the struct, could
> it restart from the truncated index and redundantly iterate over
> already-resolved members? With a very large number of members, could this
> cause excessive CPU usage or soft lockups?
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32
2026-04-14 19:50 [PATCH bpf-next 0/6] btf: Extend vlen, kind in struct btf_type Alan Maguire
2026-04-14 19:50 ` [PATCH bpf-next 1/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
@ 2026-04-14 19:50 ` Alan Maguire
2026-04-14 21:39 ` sashiko-bot
2026-04-14 19:50 ` [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support Alan Maguire
` (3 subsequent siblings)
5 siblings, 1 reply; 21+ messages in thread
From: Alan Maguire @ 2026-04-14 19:50 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, bpf,
Alan Maguire
Now that vlen is 24 bits, btf_vlen() must return a __u32.
Adjust use cases in libbpf accordingly.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
tools/lib/bpf/btf.c | 26 +++++++++++++-------------
tools/lib/bpf/btf.h | 2 +-
tools/lib/bpf/btf_dump.c | 24 ++++++++++++------------
tools/lib/bpf/relo_core.c | 16 ++++++++--------
4 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index ceb57b46a878..8225b48ee9da 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++) {
@@ -4311,7 +4311,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 +4329,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 +4406,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 +4482,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 +4504,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 +4530,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 +5077,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 +5105,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 +5439,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* Re: [PATCH bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32
2026-04-14 19:50 ` [PATCH bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
@ 2026-04-14 21:39 ` sashiko-bot
0 siblings, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-04-14 21:39 UTC (permalink / raw)
To: Alan Maguire; +Cc: bpf
Sashiko AI review found 2 potential issue(s):
- [High] Expansion of vlen from 16-bit to 24-bit introduces severe O(N^2) complexity issues in CO-RE relocation matching.
- [High] Lack of bounds checking in `btf_type_inc_vlen` corrupts the BTF type kind field upon overflow.
--
commit 05dfc0fce969915cd3d509a4e34a33558181e95d
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.
> diff --git a/tools/lib/bpf/relo_core.c b/tools/lib/bpf/relo_core.c
> index 0ccc8f548cbaa..6ae3f2a15ad0c 100644
> --- a/tools/lib/bpf/relo_core.c
> +++ b/tools/lib/bpf/relo_core.c
[ ... ]
> @@ -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;
Can this widened vlen boundary create performance issues during CO-RE
relocation?
Looking at bpf_core_enums_match() and bpf_core_composites_match(), they
iterate over both local and target BTF type members using nested loops. With
the previous 16-bit limit, the worst-case was ~4.29 billion iterations. By
expanding vlen to 24 bits (max 16.7 million), the worst-case iterations
expand to ~281 trillion.
Could a crafted BTF payload stall the libbpf parser and consuming user-space
daemons for a significant amount of time?
Since vlen has been expanded to 24 bits, could we also overflow the kind
field when adding elements to a BTF type?
tools/lib/bpf/btf.c:btf_type_inc_vlen() {
t->info = btf_type_info(btf_kind(t), btf_vlen(t) + 1, btf_kflag(t));
}
tools/lib/bpf/libbpf_internal.h:btf_type_info() {
return (kflag << 31) | (kind << 24) | vlen;
}
If a program dynamically builds a BTF type and exceeds 16,777,215 elements,
vlen reaches 1 << 24. Since the vlen and kind fields are contiguous, does
this mutate the structure's type kind rather than safely rejecting the
overflow?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260414195019.684531-1-alan.maguire@oracle.com?part=2
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support
2026-04-14 19:50 [PATCH bpf-next 0/6] btf: Extend vlen, kind in struct btf_type Alan Maguire
2026-04-14 19:50 ` [PATCH bpf-next 1/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
2026-04-14 19:50 ` [PATCH bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
@ 2026-04-14 19:50 ` Alan Maguire
2026-04-14 20:29 ` bot+bpf-ci
` (3 more replies)
2026-04-14 19:50 ` [PATCH bpf-next 4/6] bpftool: Support 24-bit vlen Alan Maguire
` (2 subsequent siblings)
5 siblings, 4 replies; 21+ messages in thread
From: Alan Maguire @ 2026-04-14 19:50 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, 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 | 39 +++++++++++++++++++++++++++++++++
tools/lib/bpf/libbpf.c | 17 +++++++++++++-
tools/lib/bpf/libbpf_internal.h | 2 ++
3 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
index 4f19a0d79b0c..4a75d6717bbb 100644
--- a/tools/lib/bpf/features.c
+++ b/tools/lib/bpf/features.c
@@ -615,6 +615,42 @@ static int probe_kern_btf_layout(int token_fd)
(char *)layout, token_fd));
}
+static int probe_kern_btf_vlen_kind_extended(int token_fd)
+{
+ struct btf *btf;
+ int ret = 0;
+ __s32 id;
+ int err;
+
+ btf = btf__load_vmlinux_btf();
+ err = libbpf_get_error(btf);
+ if (err)
+ return err;
+ id = btf__find_by_name_kind(btf, "btf_max", BTF_KIND_ENUM);
+ if (id > 0) {
+ const struct btf_type *t;
+ const struct btf_enum *e;
+ const char *name;
+ __u32 i, vlen;
+
+ t = btf__type_by_id(btf, id);
+ if (t) {
+ vlen = btf_vlen(t);
+
+ for (i = 0, e = btf_enum(t); i < vlen; i++, e++) {
+ name = btf__name_by_offset(btf, e->name_off);
+ if (!name || strcmp(name, "BTF_MAX_VLEN") != 0)
+ continue;
+ if (e->val > 0xffff)
+ ret = 1;
+ }
+ }
+ }
+ btf__free(btf);
+
+ return ret;
+}
+
typedef int (*feature_probe_fn)(int /* token_fd */);
static struct kern_feature_cache feature_cache;
@@ -699,6 +735,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..8ef1fc96b73a 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 */
+ FEAT_BTF_VLEN_KIND_EXTENDED,
__FEAT_CNT,
};
--
2.39.3
^ permalink raw reply related [flat|nested] 21+ messages in thread* Re: [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support
2026-04-14 19:50 ` [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support Alan Maguire
@ 2026-04-14 20:29 ` bot+bpf-ci
2026-04-14 21:58 ` sashiko-bot
` (2 subsequent siblings)
3 siblings, 0 replies; 21+ messages in thread
From: bot+bpf-ci @ 2026-04-14 20:29 UTC (permalink / raw)
To: alan.maguire, ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, bpf,
alan.maguire, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1131 bytes --]
> diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
> index 3781c45b46d3..8ef1fc96b73a 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 */
> + FEAT_BTF_VLEN_KIND_EXTENDED,
> __FEAT_CNT,
> };
This isn't a bug, but the comment says "BTF vlen > 65535" while the
feature also covers extended BTF kinds (> 31). The enum name itself
says VLEN_KIND_EXTENDED, the feature descriptor in features.c says
"kernel supports extended BTF vlen/kind", and the sanitization check
in bpf_object__sanitize_btf() tests both btf_vlen(t) > 0xffff and
btf_kind(t) > 0x1f.
Should the comment be something like
"Kernel supports extended BTF vlen/kind" to match?
---
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/24420385267
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support
2026-04-14 19:50 ` [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support Alan Maguire
2026-04-14 20:29 ` bot+bpf-ci
@ 2026-04-14 21:58 ` sashiko-bot
2026-04-15 1:56 ` Alexei Starovoitov
2026-04-15 15:57 ` Mykyta Yatsenko
3 siblings, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-04-14 21:58 UTC (permalink / raw)
To: Alan Maguire; +Cc: bpf
Sashiko AI review found 3 potential issue(s):
- [High] The feature probe incorrectly relies on finding an unused enum (`btf_max`) in the `vmlinux` BTF, guaranteeing it will permanently fail and falsely reject valid BPF objects.
- [High] The feature probe violates libbpf's probe architecture by reading the multi-megabyte `vmlinux` BTF instead of using lightweight `bpf()` syscalls, breaking containers and unprivileged token delegation.
- [Medium] The feature probe propagates negative errors when `vmlinux` BTF is absent, unconditionally spamming application logs with multiple warnings.
--
commit 3e8277b7bc260bfb527a032e5667d3e2d753d156
Author: Alan Maguire <alan.maguire@oracle.com>
libbpf: Add feature for kernel extended vlen/kind support
This commit adds a new feature probe to detect whether the kernel supports
extended BTF vlen and kind. It does this by loading the vmlinux BTF and
searching for an enum named btf_max with a BTF_MAX_VLEN member greater
than 0xffff.
> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
> index 4f19a0d79b0cf..4a75d6717bbbd 100644
> --- a/tools/lib/bpf/features.c
> +++ b/tools/lib/bpf/features.c
[ ... ]
> @@ -615,6 +615,42 @@ static int probe_kern_btf_layout(int token_fd)
> (char *)layout, token_fd));
> }
>
> +static int probe_kern_btf_vlen_kind_extended(int token_fd)
> +{
> + struct btf *btf;
> + int ret = 0;
> + __s32 id;
> + int err;
> +
> + btf = btf__load_vmlinux_btf();
> + err = libbpf_get_error(btf);
> + if (err)
> + return err;
If /sys/kernel/btf/vmlinux does not exist, btf__load_vmlinux_btf() returns
a negative error code. By returning this error directly, won't the
feat_supported() cache layer log a warning message? This seems like it will
spam logs on systems without vmlinux BTF.
Also, since this probe ignores token_fd, does it break BPF token delegation
for unprivileged environments? This approach introduces a dependency on
vmlinux BTF and adds parsing latency, compared to a lightweight bpf() syscall
probe.
> + id = btf__find_by_name_kind(btf, "btf_max", BTF_KIND_ENUM);
> + if (id > 0) {
> + const struct btf_type *t;
> + const struct btf_enum *e;
> + const char *name;
> + __u32 i, vlen;
> +
> + t = btf__type_by_id(btf, id);
> + if (t) {
> + vlen = btf_vlen(t);
> +
> + for (i = 0, e = btf_enum(t); i < vlen; i++, e++) {
> + name = btf__name_by_offset(btf, e->name_off);
> + if (!name || strcmp(name, "BTF_MAX_VLEN") != 0)
> + continue;
> + if (e->val > 0xffff)
> + ret = 1;
> + }
> + }
> + }
> + btf__free(btf);
> +
> + return ret;
> +}
Is enum btf_max actually instantiated in kernel C code?
If it is only used as a header construct, won't it be absent from the DWARF
debug info and the vmlinux BTF? If so, this probe would always fail to find
it, causing libbpf to unconditionally reject extended vlen/kind BTFs even on
capable kernels.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260414195019.684531-1-alan.maguire@oracle.com?part=3
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support
2026-04-14 19:50 ` [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support Alan Maguire
2026-04-14 20:29 ` bot+bpf-ci
2026-04-14 21:58 ` sashiko-bot
@ 2026-04-15 1:56 ` Alexei Starovoitov
2026-04-15 15:57 ` Mykyta Yatsenko
3 siblings, 0 replies; 21+ messages in thread
From: Alexei Starovoitov @ 2026-04-15 1:56 UTC (permalink / raw)
To: Alan Maguire
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard, Kumar Kartikeya Dwivedi, Song Liu,
Yonghong Song, Jiri Olsa, Quentin Monnet, bpf
On Tue, Apr 14, 2026 at 12:50 PM Alan Maguire <alan.maguire@oracle.com> 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 | 39 +++++++++++++++++++++++++++++++++
> tools/lib/bpf/libbpf.c | 17 +++++++++++++-
> tools/lib/bpf/libbpf_internal.h | 2 ++
> 3 files changed, 57 insertions(+), 1 deletion(-)
>
> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
> index 4f19a0d79b0c..4a75d6717bbb 100644
> --- a/tools/lib/bpf/features.c
> +++ b/tools/lib/bpf/features.c
> @@ -615,6 +615,42 @@ static int probe_kern_btf_layout(int token_fd)
> (char *)layout, token_fd));
> }
>
> +static int probe_kern_btf_vlen_kind_extended(int token_fd)
> +{
> + struct btf *btf;
> + int ret = 0;
> + __s32 id;
> + int err;
> +
> + btf = btf__load_vmlinux_btf();
> + err = libbpf_get_error(btf);
> + if (err)
> + return err;
> + id = btf__find_by_name_kind(btf, "btf_max", BTF_KIND_ENUM);
> + if (id > 0) {
> + const struct btf_type *t;
> + const struct btf_enum *e;
> + const char *name;
> + __u32 i, vlen;
> +
> + t = btf__type_by_id(btf, id);
> + if (t) {
Too much claude.
Please reduce the indent.
Easy shrink by 2 tabs.
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support
2026-04-14 19:50 ` [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support Alan Maguire
` (2 preceding siblings ...)
2026-04-15 1:56 ` Alexei Starovoitov
@ 2026-04-15 15:57 ` Mykyta Yatsenko
2026-04-16 8:57 ` Alan Maguire
3 siblings, 1 reply; 21+ messages in thread
From: Mykyta Yatsenko @ 2026-04-15 15:57 UTC (permalink / raw)
To: Alan Maguire, ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, bpf
On 4/14/26 8:50 PM, 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 | 39 +++++++++++++++++++++++++++++++++
> tools/lib/bpf/libbpf.c | 17 +++++++++++++-
> tools/lib/bpf/libbpf_internal.h | 2 ++
> 3 files changed, 57 insertions(+), 1 deletion(-)
>
> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
> index 4f19a0d79b0c..4a75d6717bbb 100644
> --- a/tools/lib/bpf/features.c
> +++ b/tools/lib/bpf/features.c
> @@ -615,6 +615,42 @@ static int probe_kern_btf_layout(int token_fd)
> (char *)layout, token_fd));
> }
>
> +static int probe_kern_btf_vlen_kind_extended(int token_fd)
> +{
> + struct btf *btf;
> + int ret = 0;
> + __s32 id;
> + int err;
> +
> + btf = btf__load_vmlinux_btf();
> + err = libbpf_get_error(btf);
> + if (err)
> + return err;
> + id = btf__find_by_name_kind(btf, "btf_max", BTF_KIND_ENUM);
Looks like if id > 0 then extended vlen and kinds are available, so
there is no point to continue processing the enum and checking value of
the BTF_MAX_VLEN. Or is there a scenario, where BTF_MAX_VLEN goes back
to 0xffff?
> + if (id > 0) {
> + const struct btf_type *t;
> + const struct btf_enum *e;
> + const char *name;
> + __u32 i, vlen;
> +
> + t = btf__type_by_id(btf, id);
> + if (t) {
> + vlen = btf_vlen(t);
> +
> + for (i = 0, e = btf_enum(t); i < vlen; i++, e++) {
> + name = btf__name_by_offset(btf, e->name_off);
> + if (!name || strcmp(name, "BTF_MAX_VLEN") != 0)
> + continue;
> + if (e->val > 0xffff)
> + ret = 1;
> + }
> + }
> + }
> + btf__free(btf);
> +
> + return ret;
> +}
> +
> typedef int (*feature_probe_fn)(int /* token_fd */);
>
> static struct kern_feature_cache feature_cache;
> @@ -699,6 +735,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..8ef1fc96b73a 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 */
> + FEAT_BTF_VLEN_KIND_EXTENDED,
> __FEAT_CNT,
> };
>
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support
2026-04-15 15:57 ` Mykyta Yatsenko
@ 2026-04-16 8:57 ` Alan Maguire
2026-04-16 14:15 ` Alexei Starovoitov
0 siblings, 1 reply; 21+ messages in thread
From: Alan Maguire @ 2026-04-16 8:57 UTC (permalink / raw)
To: Mykyta Yatsenko, ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, bpf
On 15/04/2026 16:57, Mykyta Yatsenko wrote:
>
>
> On 4/14/26 8:50 PM, 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 | 39 +++++++++++++++++++++++++++++++++
>> tools/lib/bpf/libbpf.c | 17 +++++++++++++-
>> tools/lib/bpf/libbpf_internal.h | 2 ++
>> 3 files changed, 57 insertions(+), 1 deletion(-)
>>
>> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
>> index 4f19a0d79b0c..4a75d6717bbb 100644
>> --- a/tools/lib/bpf/features.c
>> +++ b/tools/lib/bpf/features.c
>> @@ -615,6 +615,42 @@ static int probe_kern_btf_layout(int token_fd)
>> (char *)layout, token_fd));
>> }
>> +static int probe_kern_btf_vlen_kind_extended(int token_fd)
>> +{
>> + struct btf *btf;
>> + int ret = 0;
>> + __s32 id;
>> + int err;
>> +
>> + btf = btf__load_vmlinux_btf();
>> + err = libbpf_get_error(btf);
>> + if (err)
>> + return err;
>> + id = btf__find_by_name_kind(btf, "btf_max", BTF_KIND_ENUM);
>
> Looks like if id > 0 then extended vlen and kinds are available, so there is no point to continue processing the enum and checking value of the BTF_MAX_VLEN. Or is there a scenario, where BTF_MAX_VLEN goes back to 0xffff?
>
True, the enum presence is enough here. However another point the
bots made here needs to be addressed; other BTF kernel probes rely
on the bpf syscall, loading BTF into the kernel to check for feature
support. We're better off using that approach here too since it will
work even in container envs which don't have /sys/kernel/btf availability.
We can load BTF with an extended vlen (> 0xffff) and ensure it is accepted,
like the test does in patch 5 essentially.
All that said, I think the "enum btf_max" conversion is still worthwhile,
since it's conceivable users might want some of these values in vmlinux.h,
and we can deal with any potential fallout by using redundant macro
definintions like
#define BTF_MAX_TYPE BTF_MAX_TYPE
just in case someone does rely on the UAPI macros.
Thanks for taking a look!
Alan
>> + if (id > 0) {
>> + const struct btf_type *t;
>> + const struct btf_enum *e;
>> + const char *name;
>> + __u32 i, vlen;
>> +
>> + t = btf__type_by_id(btf, id);
>> + if (t) {
>> + vlen = btf_vlen(t);
>> +
>> + for (i = 0, e = btf_enum(t); i < vlen; i++, e++) {
>> + name = btf__name_by_offset(btf, e->name_off);
>> + if (!name || strcmp(name, "BTF_MAX_VLEN") != 0)
>> + continue;
>> + if (e->val > 0xffff)
>> + ret = 1;
>> + }
>> + }
>> + }
>> + btf__free(btf);
>> +
>> + return ret;
>> +}
>> +
>> typedef int (*feature_probe_fn)(int /* token_fd */);
>> static struct kern_feature_cache feature_cache;
>> @@ -699,6 +735,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..8ef1fc96b73a 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 */
>> + FEAT_BTF_VLEN_KIND_EXTENDED,
>> __FEAT_CNT,
>> };
>>
>
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support
2026-04-16 8:57 ` Alan Maguire
@ 2026-04-16 14:15 ` Alexei Starovoitov
0 siblings, 0 replies; 21+ messages in thread
From: Alexei Starovoitov @ 2026-04-16 14:15 UTC (permalink / raw)
To: Alan Maguire, Mykyta Yatsenko, ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, bpf
On Thu Apr 16, 2026 at 1:57 AM PDT, Alan Maguire wrote:
> On 15/04/2026 16:57, Mykyta Yatsenko wrote:
>>
>>
>> On 4/14/26 8:50 PM, 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 | 39 +++++++++++++++++++++++++++++++++
>>> tools/lib/bpf/libbpf.c | 17 +++++++++++++-
>>> tools/lib/bpf/libbpf_internal.h | 2 ++
>>> 3 files changed, 57 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
>>> index 4f19a0d79b0c..4a75d6717bbb 100644
>>> --- a/tools/lib/bpf/features.c
>>> +++ b/tools/lib/bpf/features.c
>>> @@ -615,6 +615,42 @@ static int probe_kern_btf_layout(int token_fd)
>>> (char *)layout, token_fd));
>>> }
>>> +static int probe_kern_btf_vlen_kind_extended(int token_fd)
>>> +{
>>> + struct btf *btf;
>>> + int ret = 0;
>>> + __s32 id;
>>> + int err;
>>> +
>>> + btf = btf__load_vmlinux_btf();
>>> + err = libbpf_get_error(btf);
>>> + if (err)
>>> + return err;
>>> + id = btf__find_by_name_kind(btf, "btf_max", BTF_KIND_ENUM);
>>
>> Looks like if id > 0 then extended vlen and kinds are available, so there is no point to continue processing the enum and checking value of the BTF_MAX_VLEN. Or is there a scenario, where BTF_MAX_VLEN goes back to 0xffff?
>>
>
> True, the enum presence is enough here. However another point the
> bots made here needs to be addressed; other BTF kernel probes rely
> on the bpf syscall, loading BTF into the kernel to check for feature
> support. We're better off using that approach here too since it will
> work even in container envs which don't have /sys/kernel/btf availability.
If containers cannot access vmlinux BTF than they will fail loading
all progs that need CO-RE. So I don't think we really need syscall
based feature detection. If it's easy enough, sure, we can have it too.
But enum is enough. The verifier exposes its features via BPF_FEAT* enum only.
See enum bpf_features.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH bpf-next 4/6] bpftool: Support 24-bit vlen
2026-04-14 19:50 [PATCH bpf-next 0/6] btf: Extend vlen, kind in struct btf_type Alan Maguire
` (2 preceding siblings ...)
2026-04-14 19:50 ` [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support Alan Maguire
@ 2026-04-14 19:50 ` Alan Maguire
2026-04-14 22:12 ` sashiko-bot
2026-04-14 19:50 ` [PATCH bpf-next 5/6] selftests/bpf: Test BTF sanitization rejection for invalid vlen Alan Maguire
2026-04-14 19:50 ` [PATCH bpf-next 6/6] selftests/bpf: Fix up btf/invalid test for extended kind Alan Maguire
5 siblings, 1 reply; 21+ messages in thread
From: Alan Maguire @ 2026-04-14 19:50 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, 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/gen.c | 16 +++++++++-------
2 files changed, 15 insertions(+), 18 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/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* Re: [PATCH bpf-next 4/6] bpftool: Support 24-bit vlen
2026-04-14 19:50 ` [PATCH bpf-next 4/6] bpftool: Support 24-bit vlen Alan Maguire
@ 2026-04-14 22:12 ` sashiko-bot
0 siblings, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-04-14 22:12 UTC (permalink / raw)
To: Alan Maguire; +Cc: bpf
Sashiko AI review found 1 potential issue(s):
- [Medium] Infinite loop in bpftool when dumping BTF enum types with 65536 or more members.
--
commit 0557506c731dab5c8d22900a9797fac53be5f625
Author: Alan Maguire <alan.maguire@oracle.com>
bpftool: Support 24-bit vlen
This commit updates bpftool to handle the new 24-bit BTF vlen by changing
variables and loop counters from 16-bit to 32-bit integers across various
BTF dumping functions.
> diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c
> index 2e899e9400341..6ef908adf3a4a 100644
> --- a/tools/bpf/bpftool/btf.c
> +++ b/tools/bpf/bpftool/btf.c
[ ... ]
> @@ -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;
Are there missing updates to btf_dumper_enum() and btf_dumper_enum64() in
tools/bpf/bpftool/btf_dumper.c?
In btf_dumper_enum(), the loop counter i is still declared as a 16-bit
integer:
static int btf_dumper_enum(const struct btf_dumper *d,
const struct btf_type *t,
const void *data)
{
const struct btf_enum *enums = btf_enum(t);
__s64 value;
__u16 i;
...
for (i = 0; i < btf_vlen(t); i++) {
if (value == enums[i].val) {
...
If a BTF enum type has 65536 or more members, btf_vlen(t) will return a value
greater than or equal to 65536. The __u16 i counter will overflow to 0 upon
reaching 65536, meaning i < btf_vlen(t) will always remain true.
If the dumped variable's value does not match any of the first 65536 enum
members, will the function loop infinitely instead of falling back to
jsonw_int()?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260414195019.684531-1-alan.maguire@oracle.com?part=4
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH bpf-next 5/6] selftests/bpf: Test BTF sanitization rejection for invalid vlen
2026-04-14 19:50 [PATCH bpf-next 0/6] btf: Extend vlen, kind in struct btf_type Alan Maguire
` (3 preceding siblings ...)
2026-04-14 19:50 ` [PATCH bpf-next 4/6] bpftool: Support 24-bit vlen Alan Maguire
@ 2026-04-14 19:50 ` Alan Maguire
2026-04-14 22:26 ` sashiko-bot
2026-04-14 19:50 ` [PATCH bpf-next 6/6] selftests/bpf: Fix up btf/invalid test for extended kind Alan Maguire
5 siblings, 1 reply; 21+ messages in thread
From: Alan Maguire @ 2026-04-14 19:50 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, 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 | 64 ++++++++++++++++++-
1 file changed, 63 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..f41cea5a769a 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,65 @@ 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;
+
+ 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;
+ btf__add_int(btf, "int", 4, BTF_INT_SIGNED);
+ btf__add_var(btf, "var1", 0, 1);
+ btf__add_datasec(btf, "datasec1", BTF_MAX_VLEN);
+ for (i = 0; i <= 0xffff; i++)
+ btf__add_datasec_var_info(btf, 2, i * 4, 4);
+
+ /* 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")) {
+ sanitized = NULL;
+ 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);
+ if (!ASSERT_OK_PTR(sanitized, "bpf_object__sanitize_btf_should_succeed"))
+ sanitized = NULL;
+
+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* Re: [PATCH bpf-next 5/6] selftests/bpf: Test BTF sanitization rejection for invalid vlen
2026-04-14 19:50 ` [PATCH bpf-next 5/6] selftests/bpf: Test BTF sanitization rejection for invalid vlen Alan Maguire
@ 2026-04-14 22:26 ` sashiko-bot
2026-04-15 16:03 ` Mykyta Yatsenko
0 siblings, 1 reply; 21+ messages in thread
From: sashiko-bot @ 2026-04-14 22:26 UTC (permalink / raw)
To: Alan Maguire; +Cc: bpf
Sashiko AI review found 3 potential issue(s):
- [Low] Leaking the BTF object on unexpected success of sanitization.
- [Low] Lack of error checks for BTF construction calls.
- [Low] Using `BTF_MAX_VLEN` as the `byte_sz` argument in `btf__add_datasec()`.
--
commit 9c5af444155b34aa840793bf185bc0c0aaa04f3f
Author: Alan Maguire <alan.maguire@oracle.com>
selftests/bpf: Test BTF sanitization rejection for invalid vlen
This patch adds a selftest to verify that BTF objects with extended vlen
are properly rejected by kernels that do not support the extended feature.
It simulates the lack of support using the feature cache and checks if
sanitization fails when the vlen limit is surpassed.
> diff --git a/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c b/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
> index 652b51efafc27..f41cea5a769a2 100644
> --- a/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
> +++ b/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
[ ... ]
> @@ -95,3 +95,65 @@ void test_btf_sanitize_layout(void)
> +static void test_btf_sanitize_extended(void)
> +{
[ ... ]
> + btf = btf__new_empty();
> + if (!ASSERT_OK_PTR(btf, "empty_btf"))
> + goto out;
> + btf__add_int(btf, "int", 4, BTF_INT_SIGNED);
> + btf__add_var(btf, "var1", 0, 1);
Are we missing error checks on these btf__add_*() calls?
If any of these allocations silently fail, the test might proceed with an
incomplete BTF object that hasn't actually surpassed the vlen limit. This
would cause the subsequent bpf_object__sanitize_btf() call to unexpectedly
succeed, failing the test for the wrong reason.
> + btf__add_datasec(btf, "datasec1", BTF_MAX_VLEN);
Is it intentional to use BTF_MAX_VLEN for the byte_sz argument here?
BTF_MAX_VLEN is a bitmask representing the maximum number of items, not a byte
size. Using a proper calculated byte size like 0x10000 * 4 might be clearer.
> + for (i = 0; i <= 0xffff; i++)
> + btf__add_datasec_var_info(btf, 2, i * 4, 4);
> +
> + /* 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")) {
> + sanitized = NULL;
If the first bpf_object__sanitize_btf() call unexpectedly succeeds, sanitized
will hold a valid pointer.
Doesn't setting it to NULL before the goto out path leak the memory, since
btf__free(sanitized) will be called with a NULL pointer at the end of the
function?
> + goto out;
> + }
> + /* Now switch extended feature on and ensure success. */
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260414195019.684531-1-alan.maguire@oracle.com?part=5
^ permalink raw reply [flat|nested] 21+ messages in thread* Re: [PATCH bpf-next 5/6] selftests/bpf: Test BTF sanitization rejection for invalid vlen
2026-04-14 22:26 ` sashiko-bot
@ 2026-04-15 16:03 ` Mykyta Yatsenko
0 siblings, 0 replies; 21+ messages in thread
From: Mykyta Yatsenko @ 2026-04-15 16:03 UTC (permalink / raw)
To: sashiko, Alan Maguire; +Cc: bpf
On 4/14/26 11:26 PM, sashiko-bot@kernel.org wrote:
> Sashiko AI review found 3 potential issue(s):
> - [Low] Leaking the BTF object on unexpected success of sanitization.
> - [Low] Lack of error checks for BTF construction calls.
> - [Low] Using `BTF_MAX_VLEN` as the `byte_sz` argument in `btf__add_datasec()`.
> --
>
> commit 9c5af444155b34aa840793bf185bc0c0aaa04f3f
> Author: Alan Maguire <alan.maguire@oracle.com>
>
> selftests/bpf: Test BTF sanitization rejection for invalid vlen
>
> This patch adds a selftest to verify that BTF objects with extended vlen
> are properly rejected by kernels that do not support the extended feature.
> It simulates the lack of support using the feature cache and checks if
> sanitization fails when the vlen limit is surpassed.
>
>> diff --git a/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c b/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
>> index 652b51efafc27..f41cea5a769a2 100644
>> --- a/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
>> +++ b/tools/testing/selftests/bpf/prog_tests/btf_sanitize.c
> [ ... ]
>> @@ -95,3 +95,65 @@ void test_btf_sanitize_layout(void)
>> +static void test_btf_sanitize_extended(void)
>> +{
> [ ... ]
>> + btf = btf__new_empty();
>> + if (!ASSERT_OK_PTR(btf, "empty_btf"))
>> + goto out;
>> + btf__add_int(btf, "int", 4, BTF_INT_SIGNED);
>> + btf__add_var(btf, "var1", 0, 1);
>
> Are we missing error checks on these btf__add_*() calls?
>
> If any of these allocations silently fail, the test might proceed with an
> incomplete BTF object that hasn't actually surpassed the vlen limit. This
> would cause the subsequent bpf_object__sanitize_btf() call to unexpectedly
> succeed, failing the test for the wrong reason.
>
>> + btf__add_datasec(btf, "datasec1", BTF_MAX_VLEN);
>
> Is it intentional to use BTF_MAX_VLEN for the byte_sz argument here?
>
> BTF_MAX_VLEN is a bitmask representing the maximum number of items, not a byte
> size. Using a proper calculated byte size like 0x10000 * 4 might be clearer.
>
>> + for (i = 0; i <= 0xffff; i++)
>> + btf__add_datasec_var_info(btf, 2, i * 4, 4);
>> +
>> + /* 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")) {
>> + sanitized = NULL;
>
> If the first bpf_object__sanitize_btf() call unexpectedly succeeds, sanitized
> will hold a valid pointer.
>
> Doesn't setting it to NULL before the goto out path leak the memory, since
> btf__free(sanitized) will be called with a NULL pointer at the end of the
> function?
>
This is no leak, but setting to NULL is not needed, because btf__free()
checks IS_ERR_OR_NULL(btf).
>> + goto out;
>> + }
>> + /* Now switch extended feature on and ensure success. */
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH bpf-next 6/6] selftests/bpf: Fix up btf/invalid test for extended kind
2026-04-14 19:50 [PATCH bpf-next 0/6] btf: Extend vlen, kind in struct btf_type Alan Maguire
` (4 preceding siblings ...)
2026-04-14 19:50 ` [PATCH bpf-next 5/6] selftests/bpf: Test BTF sanitization rejection for invalid vlen Alan Maguire
@ 2026-04-14 19:50 ` Alan Maguire
2026-04-14 22:32 ` sashiko-bot
5 siblings, 1 reply; 21+ messages in thread
From: Alan Maguire @ 2026-04-14 19:50 UTC (permalink / raw)
To: ast, daniel, andrii
Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, 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.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
---
tools/testing/selftests/bpf/prog_tests/btf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/btf.c b/tools/testing/selftests/bpf/prog_tests/btf.c
index 054ecb6b1e9f..07b1ee0eba37 100644
--- a/tools/testing/selftests/bpf/prog_tests/btf.c
+++ b/tools/testing/selftests/bpf/prog_tests/btf.c
@@ -1924,7 +1924,7 @@ 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),
@@ -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* Re: [PATCH bpf-next 6/6] selftests/bpf: Fix up btf/invalid test for extended kind
2026-04-14 19:50 ` [PATCH bpf-next 6/6] selftests/bpf: Fix up btf/invalid test for extended kind Alan Maguire
@ 2026-04-14 22:32 ` sashiko-bot
0 siblings, 0 replies; 21+ messages in thread
From: sashiko-bot @ 2026-04-14 22:32 UTC (permalink / raw)
To: Alan Maguire; +Cc: bpf
Sashiko AI review found 1 potential issue(s):
- [Low] The selftest uses a hardcoded BTF kind value of 32 (0x20000000) to test for an 'Invalid kind', which introduces test fragility.
--
commit bc86ba6ba24921947f8757ebe8a56756c77195e9
Author: Alan Maguire <alan.maguire@oracle.com>
selftests/bpf: Fix up btf/invalid test for extended kind
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.
> diff --git a/tools/testing/selftests/bpf/prog_tests/btf.c b/tools/testing/selftests/bpf/prog_tests/btf.c
> index 054ecb6b1e9f1..07b1ee0eba372 100644
> --- a/tools/testing/selftests/bpf/prog_tests/btf.c
> +++ b/tools/testing/selftests/bpf/prog_tests/btf.c
> @@ -1924,7 +1924,7 @@ 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),
Since the reason for extending the kind field was to support more than 32
kinds, does using a hardcoded kind value of 32 (0x20000000) introduce
fragility into this selftest?
Once kind 32 is eventually implemented in the kernel, this test might
spuriously fail. To make the test robust against future additions, should
this use the maximum 7-bit value (127, i.e., 0x7f000000) or another
dynamically guaranteed invalid kind?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260414195019.684531-1-alan.maguire@oracle.com?part=6
^ permalink raw reply [flat|nested] 21+ messages in thread