public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 bpf-next 0/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits
@ 2026-04-17 14:30 Alan Maguire
  2026-04-17 14:30 ` [PATCH v3 bpf-next 1/6] " Alan Maguire
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Alan Maguire @ 2026-04-17 14:30 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 kinds, but BTF location information will
take 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.  Also adds
bounds checking for max vlen.

Patch 3 cleans up __u16 vlen usage in bpftool.

Patch 4 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.

Patch 5 fixes up __u16 vlen usage in selftests/bpf.

Patch 6 syncs BTF documentation with UAPI changes.

Changes since v2 [1]:

- dropped backwards-compatibility macros (Alexei, patch 1)
- added additional vlen bounds check in btf__add_field()
  (sashiko, bpf bot, patch 2)
- dropped sanitization check in libbpf as older kernels will
  reject BTF with extended vlen/kinds using BTF info mask
  (Alexei)
- fix more vlen assumptions in prog_test/ctx_rewrite.c
  (sashiko, patch 5)

Changes since v1 [2]:

- 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/20260416143904.1220662-1-alan.maguire@oracle.com/
[2] https://lore.kernel.org/bpf/20260414195019.684531-1-alan.maguire@oracle.com/

Alan Maguire (6):
  bpf: Extend BTF UAPI vlen, kinds to use unused bits
  libbpf: Adjust btf_vlen() to return a __u32
  bpftool: Support 24-bit 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                      | 26 +++++-----
 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                | 26 +++++-----
 tools/lib/bpf/btf.c                           | 50 ++++++++++++-------
 tools/lib/bpf/btf.h                           |  2 +-
 tools/lib/bpf/btf_dump.c                      | 24 ++++-----
 tools/lib/bpf/relo_core.c                     | 16 +++---
 tools/testing/selftests/bpf/prog_tests/btf.c  |  8 +--
 .../bpf/prog_tests/btf_dedup_split.c          |  3 +-
 .../selftests/bpf/prog_tests/ctx_rewrite.c    |  3 +-
 tools/testing/selftests/bpf/test_progs.c      |  2 +-
 16 files changed, 119 insertions(+), 115 deletions(-)

-- 
2.39.3


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v3 bpf-next 1/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits
  2026-04-17 14:30 [PATCH v3 bpf-next 0/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
@ 2026-04-17 14:30 ` Alan Maguire
  2026-04-17 18:11   ` Mykyta Yatsenko
  2026-04-17 14:30 ` [PATCH v3 bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Alan Maguire @ 2026-04-17 14:30 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.

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               | 27 ++++++++++-----------------
 tools/include/uapi/linux/btf.h | 26 ++++++++++++++------------
 4 files changed, 40 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..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..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..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] 14+ messages in thread

* [PATCH v3 bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32
  2026-04-17 14:30 [PATCH v3 bpf-next 0/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
  2026-04-17 14:30 ` [PATCH v3 bpf-next 1/6] " Alan Maguire
@ 2026-04-17 14:30 ` Alan Maguire
  2026-04-17 17:07   ` sashiko-bot
  2026-04-17 18:26   ` Mykyta Yatsenko
  2026-04-17 14:30 ` [PATCH v3 bpf-next 3/6] bpftool: Support 24-bit vlen Alan Maguire
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 14+ messages in thread
From: Alan Maguire @ 2026-04-17 14:30 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       | 50 +++++++++++++++++++++++++--------------
 tools/lib/bpf/btf.h       |  2 +-
 tools/lib/bpf/btf_dump.c  | 24 +++++++++----------
 tools/lib/bpf/relo_core.c | 16 ++++++-------
 4 files changed, 53 insertions(+), 39 deletions(-)

diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index ceb57b46a878..267904939098 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -421,7 +421,7 @@ static int btf_type_size_unknown(const struct btf *btf, const struct btf_type *t
 {
 	__u32 l_cnt = btf->hdr.layout_len / sizeof(struct btf_layout);
 	struct btf_layout *l = btf->layout;
-	__u16 vlen = btf_vlen(t);
+	__u32 vlen = btf_vlen(t);
 	__u32 kind = btf_kind(t);
 
 	/* Fall back to base BTF if needed as they share layout information */
@@ -454,7 +454,7 @@ static int btf_type_size_unknown(const struct btf *btf, const struct btf_type *t
 static int btf_type_size(const struct btf *btf, const struct btf_type *t)
 {
 	const int base_size = sizeof(struct btf_type);
-	__u16 vlen = btf_vlen(t);
+	__u32 vlen = btf_vlen(t);
 
 	switch (btf_kind(t)) {
 	case BTF_KIND_FWD:
@@ -506,7 +506,7 @@ static int btf_bswap_type_rest(struct btf_type *t)
 	struct btf_array *a;
 	struct btf_param *p;
 	struct btf_enum *e;
-	__u16 vlen = btf_vlen(t);
+	__u32 vlen = btf_vlen(t);
 	int i;
 
 	switch (btf_kind(t)) {
@@ -1007,7 +1007,7 @@ int btf__align_of(const struct btf *btf, __u32 id)
 	case BTF_KIND_STRUCT:
 	case BTF_KIND_UNION: {
 		const struct btf_member *m = btf_members(t);
-		__u16 vlen = btf_vlen(t);
+		__u32 vlen = btf_vlen(t);
 		int i, max_align = 1, align;
 
 		for (i = 0; i < vlen; i++, m++) {
@@ -2121,9 +2121,12 @@ static void *btf_add_type_mem(struct btf *btf, size_t add_sz)
 			      btf->hdr.type_len, UINT_MAX, add_sz);
 }
 
-static void btf_type_inc_vlen(struct btf_type *t)
+static int btf_type_inc_vlen(struct btf_type *t)
 {
+	if (btf_vlen(t) == BTF_MAX_VLEN)
+		return -ENOSPC;
 	t->info = btf_type_info(btf_kind(t), btf_vlen(t) + 1, btf_kflag(t));
+	return 0;
 }
 
 static void btf_hdr_update_type_len(struct btf *btf, int new_len)
@@ -2652,6 +2655,8 @@ int btf__add_field(struct btf *btf, const char *name, int type_id,
 	t = btf_last_type(btf);
 	if (!btf_is_composite(t))
 		return libbpf_err(-EINVAL);
+	if (btf_vlen(t) == BTF_MAX_VLEN)
+		return libbpf_err(-ENOSPC);
 
 	if (validate_type_id(type_id))
 		return libbpf_err(-EINVAL);
@@ -2686,6 +2691,7 @@ int btf__add_field(struct btf *btf, const char *name, int type_id,
 
 	/* btf_add_type_mem can invalidate t pointer */
 	t = btf_last_type(btf);
+
 	/* update parent type's vlen and kflag */
 	t->info = btf_type_info(btf_kind(t), btf_vlen(t) + 1, is_bitfield || btf_kflag(t));
 
@@ -2796,7 +2802,9 @@ int btf__add_enum_value(struct btf *btf, const char *name, __s64 value)
 
 	/* update parent type's vlen */
 	t = btf_last_type(btf);
-	btf_type_inc_vlen(t);
+	err = btf_type_inc_vlen(t);
+	if (err)
+		return libbpf_err(err);
 
 	/* if negative value, set signedness to signed */
 	if (value < 0)
@@ -2873,7 +2881,9 @@ int btf__add_enum64_value(struct btf *btf, const char *name, __u64 value)
 
 	/* update parent type's vlen */
 	t = btf_last_type(btf);
-	btf_type_inc_vlen(t);
+	err = btf_type_inc_vlen(t);
+	if (err)
+		return libbpf_err(err);
 
 	btf_hdr_update_type_len(btf, btf->hdr.type_len + sz);
 	return 0;
@@ -3115,7 +3125,9 @@ int btf__add_func_param(struct btf *btf, const char *name, int type_id)
 
 	/* update parent type's vlen */
 	t = btf_last_type(btf);
-	btf_type_inc_vlen(t);
+	err = btf_type_inc_vlen(t);
+	if (err)
+		return libbpf_err(err);
 
 	btf_hdr_update_type_len(btf, btf->hdr.type_len + sz);
 	return 0;
@@ -3257,7 +3269,9 @@ int btf__add_datasec_var_info(struct btf *btf, int var_type_id, __u32 offset, __
 
 	/* update parent type's vlen */
 	t = btf_last_type(btf);
-	btf_type_inc_vlen(t);
+	err = btf_type_inc_vlen(t);
+	if (err)
+		return libbpf_err(err);
 
 	btf_hdr_update_type_len(btf, btf->hdr.type_len + sz);
 	return 0;
@@ -4311,7 +4325,7 @@ static long btf_hash_enum(struct btf_type *t)
 static bool btf_equal_enum_members(struct btf_type *t1, struct btf_type *t2)
 {
 	const struct btf_enum *m1, *m2;
-	__u16 vlen;
+	__u32 vlen;
 	int i;
 
 	vlen = btf_vlen(t1);
@@ -4329,7 +4343,7 @@ static bool btf_equal_enum_members(struct btf_type *t1, struct btf_type *t2)
 static bool btf_equal_enum64_members(struct btf_type *t1, struct btf_type *t2)
 {
 	const struct btf_enum64 *m1, *m2;
-	__u16 vlen;
+	__u32 vlen;
 	int i;
 
 	vlen = btf_vlen(t1);
@@ -4406,7 +4420,7 @@ static long btf_hash_struct(struct btf_type *t)
 static bool btf_shallow_equal_struct(struct btf_type *t1, struct btf_type *t2)
 {
 	const struct btf_member *m1, *m2;
-	__u16 vlen;
+	__u32 vlen;
 	int i;
 
 	if (!btf_equal_common(t1, t2))
@@ -4482,7 +4496,7 @@ static bool btf_compat_array(struct btf_type *t1, struct btf_type *t2)
 static long btf_hash_fnproto(struct btf_type *t)
 {
 	const struct btf_param *member = btf_params(t);
-	__u16 vlen = btf_vlen(t);
+	__u32 vlen = btf_vlen(t);
 	long h = btf_hash_common(t);
 	int i;
 
@@ -4504,7 +4518,7 @@ static long btf_hash_fnproto(struct btf_type *t)
 static bool btf_equal_fnproto(struct btf_type *t1, struct btf_type *t2)
 {
 	const struct btf_param *m1, *m2;
-	__u16 vlen;
+	__u32 vlen;
 	int i;
 
 	if (!btf_equal_common(t1, t2))
@@ -4530,7 +4544,7 @@ static bool btf_equal_fnproto(struct btf_type *t1, struct btf_type *t2)
 static bool btf_compat_fnproto(struct btf_type *t1, struct btf_type *t2)
 {
 	const struct btf_param *m1, *m2;
-	__u16 vlen;
+	__u32 vlen;
 	int i;
 
 	/* skip return type ID */
@@ -5077,7 +5091,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 +5119,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 +5453,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] 14+ messages in thread

* [PATCH v3 bpf-next 3/6] bpftool: Support 24-bit vlen
  2026-04-17 14:30 [PATCH v3 bpf-next 0/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
  2026-04-17 14:30 ` [PATCH v3 bpf-next 1/6] " Alan Maguire
  2026-04-17 14:30 ` [PATCH v3 bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
@ 2026-04-17 14:30 ` Alan Maguire
  2026-04-17 18:36   ` Mykyta Yatsenko
  2026-04-17 14:30 ` [PATCH v3 bpf-next 4/6] selftests/bpf: Fix up btf/invalid test for extended kind Alan Maguire
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 14+ messages in thread
From: Alan Maguire @ 2026-04-17 14:30 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..37159e02f418 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;
+			__u32 vlen, idx_src;
 
 			name = btf__str_by_offset(info->src_btf, type->name_off);
 
-- 
2.39.3


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 bpf-next 4/6] selftests/bpf: Fix up btf/invalid test for extended kind
  2026-04-17 14:30 [PATCH v3 bpf-next 0/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
                   ` (2 preceding siblings ...)
  2026-04-17 14:30 ` [PATCH v3 bpf-next 3/6] bpftool: Support 24-bit vlen Alan Maguire
@ 2026-04-17 14:30 ` Alan Maguire
  2026-04-17 19:07   ` Mykyta Yatsenko
  2026-04-17 14:30 ` [PATCH v3 bpf-next 5/6] selftests/bpf: Fix up __u16 vlen assumptions Alan Maguire
  2026-04-17 14:30 ` [PATCH v3 bpf-next 6/6] Documentation/bpf: Update btf doc with updated vlen, kind sizes Alan Maguire
  5 siblings, 1 reply; 14+ messages in thread
From: Alan Maguire @ 2026-04-17 14:30 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] 14+ messages in thread

* [PATCH v3 bpf-next 5/6] selftests/bpf: Fix up __u16 vlen assumptions
  2026-04-17 14:30 [PATCH v3 bpf-next 0/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
                   ` (3 preceding siblings ...)
  2026-04-17 14:30 ` [PATCH v3 bpf-next 4/6] selftests/bpf: Fix up btf/invalid test for extended kind Alan Maguire
@ 2026-04-17 14:30 ` Alan Maguire
  2026-04-17 19:06   ` Mykyta Yatsenko
  2026-04-17 14:30 ` [PATCH v3 bpf-next 6/6] Documentation/bpf: Update btf doc with updated vlen, kind sizes Alan Maguire
  5 siblings, 1 reply; 14+ messages in thread
From: Alan Maguire @ 2026-04-17 14:30 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 | 3 +--
 tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c     | 3 +--
 tools/testing/selftests/bpf/test_progs.c                 | 2 +-
 4 files changed, 4 insertions(+), 6 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..6bc31236805c 100644
--- a/tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c
+++ b/tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c
@@ -487,9 +487,8 @@ 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, j;
 		__u32 id;
-		int j;
 
 		id = btf__find_by_name_kind(btf1, mod_funcs[i], BTF_KIND_FUNC);
 		if (!ASSERT_GE(id, nr_base_types, "func_id"))
diff --git a/tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c b/tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c
index 469e92869523..5064aeb8fe67 100644
--- a/tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c
+++ b/tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c
@@ -253,8 +253,7 @@ static int find_field_offset_aux(struct btf *btf, int btf_id, char *field_name,
 {
 	const struct btf_type *type = btf__type_by_id(btf, btf_id);
 	const struct btf_member *m;
-	__u16 mnum;
-	int i;
+	__u32 mnum, i;
 
 	if (!type) {
 		PRINT_FAIL("Can't find btf_type for id %d\n", btf_id);
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] 14+ messages in thread

* [PATCH v3 bpf-next 6/6] Documentation/bpf: Update btf doc with updated vlen, kind sizes
  2026-04-17 14:30 [PATCH v3 bpf-next 0/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
                   ` (4 preceding siblings ...)
  2026-04-17 14:30 ` [PATCH v3 bpf-next 5/6] selftests/bpf: Fix up __u16 vlen assumptions Alan Maguire
@ 2026-04-17 14:30 ` Alan Maguire
  2026-04-17 15:39   ` bot+bpf-ci
  5 siblings, 1 reply; 14+ messages in thread
From: Alan Maguire @ 2026-04-17 14:30 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] 14+ messages in thread

* Re: [PATCH v3 bpf-next 6/6] Documentation/bpf: Update btf doc with updated vlen, kind sizes
  2026-04-17 14:30 ` [PATCH v3 bpf-next 6/6] Documentation/bpf: Update btf doc with updated vlen, kind sizes Alan Maguire
@ 2026-04-17 15:39   ` bot+bpf-ci
  0 siblings, 0 replies; 14+ messages in thread
From: bot+bpf-ci @ 2026-04-17 15:39 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: 1977 bytes --]

> 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)

Does the kind field documentation accurately match the UAPI implementation?
The UAPI defines BTF_INFO_KIND as:

    #define BTF_INFO_KIND(info)     (((info) >> 24) & 0x7f)

The mask 0x7f is 7 bits, which means kind occupies bits 24-30. This
documentation shows "bits 24-30" which appears correct.

However, checking the actual implementation confirms the kind field uses
only 7 bits (0x7f mask), leaving bit 31 exclusively for kind_flag.


Should the documentation have removed the "bits 16-23: unused" description?
The previous documentation listed bits 16-23 as unused, but after expanding
vlen to bits 0-23, these bits are now part of vlen. The current bit
allocation is:

    - Bits 0-23: vlen (24 bits)
    - Bits 24-30: kind (7 bits)
    - Bit 31: kind_flag (1 bit)

The patch removes the "bits 16-23: unused" line from the struct comment,
which correctly reflects that these bits are now part of the expanded vlen
field.

>           * bit     31: kind_flag, currently used by
>           *             struct, union, enum, fwd, enum64,
>           *             decl_tag and type_tag


---
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/24570998051

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32
  2026-04-17 14:30 ` [PATCH v3 bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
@ 2026-04-17 17:07   ` sashiko-bot
  2026-04-17 18:26   ` Mykyta Yatsenko
  1 sibling, 0 replies; 14+ messages in thread
From: sashiko-bot @ 2026-04-17 17:07 UTC (permalink / raw)
  To: Alan Maguire; +Cc: bpf

Sashiko AI review found 1 potential issue(s):
- [High] On 32-bit systems, `btf_parse_type_sec()` is vulnerable to pointer arithmetic wrap-around due to missing strict bounds checking, allowing an attacker-crafted BTF layout to bypass safety checks and cause out-of-bounds memory access.
--

commit 0d6d9306686384cb94334ae8845f954db44a9f74
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
> index ceb57b46a8782..267904939098c 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);

Can this lead to a pointer arithmetic wrap-around regression on 32-bit
systems?

The size is calculated later in this function using unsigned 32-bit
arithmetic and returned as a signed int:

    return sizeof(struct btf_type) + l[kind].info_sz + vlen * l[kind].elem_sz;

An attacker could provide a custom layout with an artificially large elem_sz
(e.g., 2,000,000,000). For a type with vlen = 1, the calculated size fits
within a positive signed 32-bit int and is returned as a valid positive
type_size.

When btf_parse_type_sec() checks if next_type + type_size > end_type, it
evaluates this using 32-bit pointer arithmetic. If next_type is located high
in the address space, adding 2,000,000,000 wraps around the 32-bit boundary
to a numerically smaller low address, incorrectly passing the bounds check.

This causes next_type to advance to the wrapped address, allowing subsequent
loop iterations to read arbitrary memory and potentially cause out-of-bounds
accesses or crashes.

While this parser logic issue predates this patch, should we address it here
by safely checking the offset instead? For example:

    if ((size_t)type_size > (size_t)((char *)end_type - (char *)next_type))

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260417143023.1551481-1-alan.maguire@oracle.com?part=2

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 bpf-next 1/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits
  2026-04-17 14:30 ` [PATCH v3 bpf-next 1/6] " Alan Maguire
@ 2026-04-17 18:11   ` Mykyta Yatsenko
  0 siblings, 0 replies; 14+ messages in thread
From: Mykyta Yatsenko @ 2026-04-17 18:11 UTC (permalink / raw)
  To: Alan Maguire, ast, daniel, andrii
  Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, bpf



On 4/17/26 3:30 PM, Alan Maguire wrote:
> 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>
> ---

It looks like all callsites of vlen have been migrated to u32 (except 
the ones that are guaranteed to work with narrower types: 
btf_func_linkage(), cs->num_params).
Extending kind from 5 to 7 bits does not require modifying users at all.

Acked-by: Mykyta Yatsenko <yatsenko@meta.com>

>   include/linux/btf.h            |  4 ++--
>   include/uapi/linux/btf.h       | 26 ++++++++++++++------------
>   kernel/bpf/btf.c               | 27 ++++++++++-----------------
>   tools/include/uapi/linux/btf.h | 26 ++++++++++++++------------
>   4 files changed, 40 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..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..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..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 {


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32
  2026-04-17 14:30 ` [PATCH v3 bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
  2026-04-17 17:07   ` sashiko-bot
@ 2026-04-17 18:26   ` Mykyta Yatsenko
  1 sibling, 0 replies; 14+ messages in thread
From: Mykyta Yatsenko @ 2026-04-17 18:26 UTC (permalink / raw)
  To: Alan Maguire, ast, daniel, andrii
  Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, bpf



On 4/17/26 3:30 PM, Alan Maguire wrote:
> 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>
> ---

Migrated all vlens in libbpf u16 -> u32, kind does not require widening.
Acked-by: Mykyta Yatsenko <yatsenko@meta.com>

>   tools/lib/bpf/btf.c       | 50 +++++++++++++++++++++++++--------------
>   tools/lib/bpf/btf.h       |  2 +-
>   tools/lib/bpf/btf_dump.c  | 24 +++++++++----------
>   tools/lib/bpf/relo_core.c | 16 ++++++-------
>   4 files changed, 53 insertions(+), 39 deletions(-)
> 
> diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
> index ceb57b46a878..267904939098 100644
> --- a/tools/lib/bpf/btf.c
> +++ b/tools/lib/bpf/btf.c
> @@ -421,7 +421,7 @@ static int btf_type_size_unknown(const struct btf *btf, const struct btf_type *t
>   {
>   	__u32 l_cnt = btf->hdr.layout_len / sizeof(struct btf_layout);
>   	struct btf_layout *l = btf->layout;
> -	__u16 vlen = btf_vlen(t);
> +	__u32 vlen = btf_vlen(t);
>   	__u32 kind = btf_kind(t);
>   
>   	/* Fall back to base BTF if needed as they share layout information */
> @@ -454,7 +454,7 @@ static int btf_type_size_unknown(const struct btf *btf, const struct btf_type *t
>   static int btf_type_size(const struct btf *btf, const struct btf_type *t)
>   {
>   	const int base_size = sizeof(struct btf_type);
> -	__u16 vlen = btf_vlen(t);
> +	__u32 vlen = btf_vlen(t);
>   
>   	switch (btf_kind(t)) {
>   	case BTF_KIND_FWD:
> @@ -506,7 +506,7 @@ static int btf_bswap_type_rest(struct btf_type *t)
>   	struct btf_array *a;
>   	struct btf_param *p;
>   	struct btf_enum *e;
> -	__u16 vlen = btf_vlen(t);
> +	__u32 vlen = btf_vlen(t);
>   	int i;
>   
>   	switch (btf_kind(t)) {
> @@ -1007,7 +1007,7 @@ int btf__align_of(const struct btf *btf, __u32 id)
>   	case BTF_KIND_STRUCT:
>   	case BTF_KIND_UNION: {
>   		const struct btf_member *m = btf_members(t);
> -		__u16 vlen = btf_vlen(t);
> +		__u32 vlen = btf_vlen(t);
>   		int i, max_align = 1, align;
>   
>   		for (i = 0; i < vlen; i++, m++) {
> @@ -2121,9 +2121,12 @@ static void *btf_add_type_mem(struct btf *btf, size_t add_sz)
>   			      btf->hdr.type_len, UINT_MAX, add_sz);
>   }
>   
> -static void btf_type_inc_vlen(struct btf_type *t)
> +static int btf_type_inc_vlen(struct btf_type *t)
>   {
> +	if (btf_vlen(t) == BTF_MAX_VLEN)
> +		return -ENOSPC;
>   	t->info = btf_type_info(btf_kind(t), btf_vlen(t) + 1, btf_kflag(t));
> +	return 0;
>   }
>   
>   static void btf_hdr_update_type_len(struct btf *btf, int new_len)
> @@ -2652,6 +2655,8 @@ int btf__add_field(struct btf *btf, const char *name, int type_id,
>   	t = btf_last_type(btf);
>   	if (!btf_is_composite(t))
>   		return libbpf_err(-EINVAL);
> +	if (btf_vlen(t) == BTF_MAX_VLEN)
> +		return libbpf_err(-ENOSPC);
>   
>   	if (validate_type_id(type_id))
>   		return libbpf_err(-EINVAL);
> @@ -2686,6 +2691,7 @@ int btf__add_field(struct btf *btf, const char *name, int type_id,
>   
>   	/* btf_add_type_mem can invalidate t pointer */
>   	t = btf_last_type(btf);
> +
>   	/* update parent type's vlen and kflag */
>   	t->info = btf_type_info(btf_kind(t), btf_vlen(t) + 1, is_bitfield || btf_kflag(t));
>   
> @@ -2796,7 +2802,9 @@ int btf__add_enum_value(struct btf *btf, const char *name, __s64 value)
>   
>   	/* update parent type's vlen */
>   	t = btf_last_type(btf);
> -	btf_type_inc_vlen(t);
> +	err = btf_type_inc_vlen(t);
> +	if (err)
> +		return libbpf_err(err);
>   
>   	/* if negative value, set signedness to signed */
>   	if (value < 0)
> @@ -2873,7 +2881,9 @@ int btf__add_enum64_value(struct btf *btf, const char *name, __u64 value)
>   
>   	/* update parent type's vlen */
>   	t = btf_last_type(btf);
> -	btf_type_inc_vlen(t);
> +	err = btf_type_inc_vlen(t);
> +	if (err)
> +		return libbpf_err(err);
>   
>   	btf_hdr_update_type_len(btf, btf->hdr.type_len + sz);
>   	return 0;
> @@ -3115,7 +3125,9 @@ int btf__add_func_param(struct btf *btf, const char *name, int type_id)
>   
>   	/* update parent type's vlen */
>   	t = btf_last_type(btf);
> -	btf_type_inc_vlen(t);
> +	err = btf_type_inc_vlen(t);
> +	if (err)
> +		return libbpf_err(err);
>   
>   	btf_hdr_update_type_len(btf, btf->hdr.type_len + sz);
>   	return 0;
> @@ -3257,7 +3269,9 @@ int btf__add_datasec_var_info(struct btf *btf, int var_type_id, __u32 offset, __
>   
>   	/* update parent type's vlen */
>   	t = btf_last_type(btf);
> -	btf_type_inc_vlen(t);
> +	err = btf_type_inc_vlen(t);
> +	if (err)
> +		return libbpf_err(err);
>   
>   	btf_hdr_update_type_len(btf, btf->hdr.type_len + sz);
>   	return 0;
> @@ -4311,7 +4325,7 @@ static long btf_hash_enum(struct btf_type *t)
>   static bool btf_equal_enum_members(struct btf_type *t1, struct btf_type *t2)
>   {
>   	const struct btf_enum *m1, *m2;
> -	__u16 vlen;
> +	__u32 vlen;
>   	int i;
>   
>   	vlen = btf_vlen(t1);
> @@ -4329,7 +4343,7 @@ static bool btf_equal_enum_members(struct btf_type *t1, struct btf_type *t2)
>   static bool btf_equal_enum64_members(struct btf_type *t1, struct btf_type *t2)
>   {
>   	const struct btf_enum64 *m1, *m2;
> -	__u16 vlen;
> +	__u32 vlen;
>   	int i;
>   
>   	vlen = btf_vlen(t1);
> @@ -4406,7 +4420,7 @@ static long btf_hash_struct(struct btf_type *t)
>   static bool btf_shallow_equal_struct(struct btf_type *t1, struct btf_type *t2)
>   {
>   	const struct btf_member *m1, *m2;
> -	__u16 vlen;
> +	__u32 vlen;
>   	int i;
>   
>   	if (!btf_equal_common(t1, t2))
> @@ -4482,7 +4496,7 @@ static bool btf_compat_array(struct btf_type *t1, struct btf_type *t2)
>   static long btf_hash_fnproto(struct btf_type *t)
>   {
>   	const struct btf_param *member = btf_params(t);
> -	__u16 vlen = btf_vlen(t);
> +	__u32 vlen = btf_vlen(t);
>   	long h = btf_hash_common(t);
>   	int i;
>   
> @@ -4504,7 +4518,7 @@ static long btf_hash_fnproto(struct btf_type *t)
>   static bool btf_equal_fnproto(struct btf_type *t1, struct btf_type *t2)
>   {
>   	const struct btf_param *m1, *m2;
> -	__u16 vlen;
> +	__u32 vlen;
>   	int i;
>   
>   	if (!btf_equal_common(t1, t2))
> @@ -4530,7 +4544,7 @@ static bool btf_equal_fnproto(struct btf_type *t1, struct btf_type *t2)
>   static bool btf_compat_fnproto(struct btf_type *t1, struct btf_type *t2)
>   {
>   	const struct btf_param *m1, *m2;
> -	__u16 vlen;
> +	__u32 vlen;
>   	int i;
>   
>   	/* skip return type ID */
> @@ -5077,7 +5091,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 +5119,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 +5453,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)


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 bpf-next 3/6] bpftool: Support 24-bit vlen
  2026-04-17 14:30 ` [PATCH v3 bpf-next 3/6] bpftool: Support 24-bit vlen Alan Maguire
@ 2026-04-17 18:36   ` Mykyta Yatsenko
  0 siblings, 0 replies; 14+ messages in thread
From: Mykyta Yatsenko @ 2026-04-17 18:36 UTC (permalink / raw)
  To: Alan Maguire, ast, daniel, andrii
  Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, bpf



On 4/17/26 3:30 PM, Alan Maguire wrote:
> 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;

in libbpf, kernel and btf_dumper.c we did not migrate those callsites 
that use int for vlen, but we do it here. Not an issue, of course, 
either way it's correct.

>   	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..37159e02f418 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;
> +			__u32 vlen, idx_src;
>   
>   			name = btf__str_by_offset(info->src_btf, type->name_off);
>   


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 bpf-next 5/6] selftests/bpf: Fix up __u16 vlen assumptions
  2026-04-17 14:30 ` [PATCH v3 bpf-next 5/6] selftests/bpf: Fix up __u16 vlen assumptions Alan Maguire
@ 2026-04-17 19:06   ` Mykyta Yatsenko
  0 siblings, 0 replies; 14+ messages in thread
From: Mykyta Yatsenko @ 2026-04-17 19:06 UTC (permalink / raw)
  To: Alan Maguire, ast, daniel, andrii
  Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, bpf



On 4/17/26 3:30 PM, Alan Maguire wrote:
> Fix up a few cases where we assume vlen is 16 bits.
> 
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> ---

Acked-by: Mykyta Yatsenko <yatsenko@meta.com>

>   tools/testing/selftests/bpf/prog_tests/btf.c             | 2 +-
>   tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c | 3 +--
>   tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c     | 3 +--
>   tools/testing/selftests/bpf/test_progs.c                 | 2 +-
>   4 files changed, 4 insertions(+), 6 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..6bc31236805c 100644
> --- a/tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c
> +++ b/tools/testing/selftests/bpf/prog_tests/btf_dedup_split.c
> @@ -487,9 +487,8 @@ 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, j;
>   		__u32 id;
> -		int j;
>   
>   		id = btf__find_by_name_kind(btf1, mod_funcs[i], BTF_KIND_FUNC);
>   		if (!ASSERT_GE(id, nr_base_types, "func_id"))
> diff --git a/tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c b/tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c
> index 469e92869523..5064aeb8fe67 100644
> --- a/tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c
> +++ b/tools/testing/selftests/bpf/prog_tests/ctx_rewrite.c
> @@ -253,8 +253,7 @@ static int find_field_offset_aux(struct btf *btf, int btf_id, char *field_name,
>   {
>   	const struct btf_type *type = btf__type_by_id(btf, btf_id);
>   	const struct btf_member *m;
> -	__u16 mnum;
> -	int i;
> +	__u32 mnum, i;
>   
>   	if (!type) {
>   		PRINT_FAIL("Can't find btf_type for id %d\n", btf_id);
> 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);


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 bpf-next 4/6] selftests/bpf: Fix up btf/invalid test for extended kind
  2026-04-17 14:30 ` [PATCH v3 bpf-next 4/6] selftests/bpf: Fix up btf/invalid test for extended kind Alan Maguire
@ 2026-04-17 19:07   ` Mykyta Yatsenko
  0 siblings, 0 replies; 14+ messages in thread
From: Mykyta Yatsenko @ 2026-04-17 19:07 UTC (permalink / raw)
  To: Alan Maguire, ast, daniel, andrii
  Cc: martin.lau, eddyz87, memxor, song, yonghong.song, jolsa, qmo, bpf



On 4/17/26 3:30 PM, Alan Maguire wrote:
> 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>
> ---

Acked-by: Mykyta Yatsenko <yatsenko@meta.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",
>   },
>   
>   {


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2026-04-17 19:07 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-17 14:30 [PATCH v3 bpf-next 0/6] bpf: Extend BTF UAPI vlen, kinds to use unused bits Alan Maguire
2026-04-17 14:30 ` [PATCH v3 bpf-next 1/6] " Alan Maguire
2026-04-17 18:11   ` Mykyta Yatsenko
2026-04-17 14:30 ` [PATCH v3 bpf-next 2/6] libbpf: Adjust btf_vlen() to return a __u32 Alan Maguire
2026-04-17 17:07   ` sashiko-bot
2026-04-17 18:26   ` Mykyta Yatsenko
2026-04-17 14:30 ` [PATCH v3 bpf-next 3/6] bpftool: Support 24-bit vlen Alan Maguire
2026-04-17 18:36   ` Mykyta Yatsenko
2026-04-17 14:30 ` [PATCH v3 bpf-next 4/6] selftests/bpf: Fix up btf/invalid test for extended kind Alan Maguire
2026-04-17 19:07   ` Mykyta Yatsenko
2026-04-17 14:30 ` [PATCH v3 bpf-next 5/6] selftests/bpf: Fix up __u16 vlen assumptions Alan Maguire
2026-04-17 19:06   ` Mykyta Yatsenko
2026-04-17 14:30 ` [PATCH v3 bpf-next 6/6] Documentation/bpf: Update btf doc with updated vlen, kind sizes Alan Maguire
2026-04-17 15:39   ` bot+bpf-ci

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox