Re: [PATCH bpf-next 3/6] libbpf: Add feature for kernel extended vlen/kind support

Mykyta Yatsenko
2026-04-15T15:57:48Z

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,
> };
>