lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAEf4BzYJpw+yEv=g9P1z0NS8Qw8PdFf7039MT0PSv30DwkjBzw@mail.gmail.com>
Date: Thu, 18 Dec 2025 15:02:29 -0800
From: Andrii Nakryiko <andrii.nakryiko@...il.com>
To: Donglin Peng <dolinux.peng@...il.com>
Cc: ast@...nel.org, eddyz87@...il.com, zhangxiaoqin@...omi.com, 
	ihor.solodrai@...ux.dev, linux-kernel@...r.kernel.org, bpf@...r.kernel.org, 
	pengdonglin <pengdonglin@...omi.com>, Alan Maguire <alan.maguire@...cle.com>
Subject: Re: [PATCH bpf-next v10 01/13] libbpf: Add BTF permutation support
 for type reordering

On Thu, Dec 18, 2025 at 3:31 AM Donglin Peng <dolinux.peng@...il.com> wrote:
>
> From: pengdonglin <pengdonglin@...omi.com>
>
> Introduce btf__permute() API to allow in-place rearrangement of BTF types.
> This function reorganizes BTF type order according to a provided array of
> type IDs, updating all type references to maintain consistency.
>
> Cc: Eduard Zingerman <eddyz87@...il.com>
> Cc: Alexei Starovoitov <ast@...nel.org>
> Cc: Andrii Nakryiko <andrii.nakryiko@...il.com>
> Cc: Alan Maguire <alan.maguire@...cle.com>
> Cc: Ihor Solodrai <ihor.solodrai@...ux.dev>
> Cc: Xiaoqin Zhang <zhangxiaoqin@...omi.com>
> Signed-off-by: pengdonglin <pengdonglin@...omi.com>
> Acked-by: Eduard Zingerman <eddyz87@...il.com>
> ---
>  tools/lib/bpf/btf.c      | 119 +++++++++++++++++++++++++++++++++++++++
>  tools/lib/bpf/btf.h      |  36 ++++++++++++
>  tools/lib/bpf/libbpf.map |   1 +
>  3 files changed, 156 insertions(+)
>
> diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
> index b136572e889a..ab204ca403dc 100644
> --- a/tools/lib/bpf/btf.c
> +++ b/tools/lib/bpf/btf.c
> @@ -5887,3 +5887,122 @@ int btf__relocate(struct btf *btf, const struct btf *base_btf)
>                 btf->owns_base = false;
>         return libbpf_err(err);
>  }
> +
> +struct btf_permute {
> +       struct btf *btf;
> +       __u32 *id_map;
> +};
> +
> +/* Callback function to remap individual type ID references */
> +static int btf_permute_remap_type_id(__u32 *type_id, void *ctx)
> +{
> +       struct btf_permute *p = ctx;
> +       __u32 new_type_id = *type_id;
> +
> +       /* refer to the base BTF or VOID type */
> +       if (new_type_id < p->btf->start_id)
> +               return 0;
> +
> +       if (new_type_id >= btf__type_cnt(p->btf))
> +               return -EINVAL;
> +
> +       *type_id = p->id_map[new_type_id - p->btf->start_id];
> +       return 0;
> +}
> +
> +int btf__permute(struct btf *btf, __u32 *id_map, __u32 id_map_cnt,
> +                const struct btf_permute_opts *opts)
> +{
> +       struct btf_permute p;
> +       struct btf_ext *btf_ext;
> +       void *nt, *new_types = NULL;
> +       __u32 *order_map = NULL;
> +       int err = 0, i;
> +       __u32 id;
> +
> +       if (!OPTS_VALID(opts, btf_permute_opts) || id_map_cnt != btf->nr_types)
> +               return libbpf_err(-EINVAL);
> +
> +       /* record the sequence of types */
> +       order_map = calloc(id_map_cnt, sizeof(*id_map));
> +       if (!order_map) {
> +               err = -ENOMEM;
> +               goto done;
> +       }
> +
> +       new_types = calloc(btf->hdr->type_len, 1);
> +       if (!new_types) {
> +               err = -ENOMEM;
> +               goto done;
> +       }
> +
> +       if (btf_ensure_modifiable(btf)) {
> +               err = -ENOMEM;
> +               goto done;
> +       }
> +
> +       for (i = 0; i < id_map_cnt; i++) {
> +               id = id_map[i];
> +               if (id < btf->start_id || id >= btf__type_cnt(btf)) {
> +                       err = -EINVAL;
> +                       goto done;
> +               }
> +               id -= btf->start_id;
> +               /* cannot be mapped to the same ID */
> +               if (order_map[id]) {
> +                       err = -EINVAL;
> +                       goto done;
> +               }
> +               order_map[id] = i + btf->start_id;
> +       }
> +
> +       p.btf = btf;
> +       p.id_map = id_map;
> +       nt = new_types;
> +       for (i = 0; i < id_map_cnt; i++) {
> +               struct btf_field_iter it;
> +               const struct btf_type *t;
> +               __u32 *type_id;
> +               int type_size;
> +
> +               id = order_map[i];
> +               t = btf__type_by_id(btf, id);
> +               type_size = btf_type_size(t);
> +               memcpy(nt, t, type_size);
> +
> +               /* fix up referenced IDs for BTF */
> +               err = btf_field_iter_init(&it, nt, BTF_FIELD_ITER_IDS);
> +               if (err)
> +                       goto done;
> +               while ((type_id = btf_field_iter_next(&it))) {
> +                       err = btf_permute_remap_type_id(type_id, &p);
> +                       if (err)
> +                               goto done;
> +               }
> +
> +               nt += type_size;
> +       }
> +
> +       /* fix up referenced IDs for btf_ext */
> +       btf_ext = OPTS_GET(opts, btf_ext, NULL);
> +       if (btf_ext) {
> +               err = btf_ext_visit_type_ids(btf_ext, btf_permute_remap_type_id, &p);
> +               if (err)
> +                       goto done;
> +       }
> +
> +       for (nt = new_types, i = 0; i < id_map_cnt; i++) {
> +               btf->type_offs[i] = nt - new_types;
> +               nt += btf_type_size(nt);
> +       }
> +
> +       free(order_map);
> +       free(btf->types_data);
> +       btf->types_data = new_types;
> +       return 0;
> +
> +done:
> +       free(order_map);
> +       free(new_types);
> +       return libbpf_err(err);
> +}
> diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
> index cc01494d6210..5d560571b1b5 100644
> --- a/tools/lib/bpf/btf.h
> +++ b/tools/lib/bpf/btf.h
> @@ -281,6 +281,42 @@ LIBBPF_API int btf__dedup(struct btf *btf, const struct btf_dedup_opts *opts);
>   */
>  LIBBPF_API int btf__relocate(struct btf *btf, const struct btf *base_btf);
>
> +struct btf_permute_opts {
> +       size_t sz;
> +       /* optional .BTF.ext info along the main BTF info */
> +       struct btf_ext *btf_ext;
> +       size_t :0;
> +};
> +#define btf_permute_opts__last_field btf_ext
> +
> +/**
> + * @brief **btf__permute()** performs in-place BTF type rearrangement
> + * @param btf BTF object to permute
> + * @param id_map Array mapping original type IDs to new IDs
> + * @param id_map_cnt Number of elements in @id_map
> + * @param opts Optional parameters for BTF extension updates
> + * @return 0 on success, negative error code on failure
> + *
> + * **btf__permute()** rearranges BTF types according to the specified ID mapping.
> + * The @id_map array defines the new type ID for each original type ID.
> + *
> + * @id_map must include all types from ID `start_id` to `btf__type_cnt(btf) - 1`.
> + * @id_map_cnt should be `btf__type_cnt(btf) - start_id`
> + * The mapping is defined as: `id_map[original_id - start_id] = new_id`

Would you mind paying attention to the feedback I left in [0]? Thank you.

The contract should be id_map[original_id] = new_id for base BTF and
id_map[original_id - btf__type_cnt(base_btf)] = new_id for split BTF.
Special BTF type #0 (VOID) is considered to be part of base BTF,
having id_map[0] = 0 is easy to check and enforce. And then it leaves
us with a simple and logical rule for id_map. For split BTF we make
necessary type ID shifts to avoid tons of wasted memory. But for base
BTF there is no need to shift anything. So mapping the original type
#X to #Y is id_map[X] = Y. Literally, "map X to Y", as simple as that.

  [0] https://lore.kernel.org/bpf/CAEf4BzY_k721TBfRSUeq5mB-7fgJhVKCeXVKO-W2EjQ0aS9AgA@mail.gmail.com/

> + *
> + * For base BTF, its `start_id` is fixed to 1, i.e. the VOID type can
> + * not be redefined or remapped and its ID is fixed to 0.
> + *
> + * For split BTF, its `start_id` can be retrieved by calling
> + * `btf__type_cnt(btf__base_btf(btf))`.
> + *
> + * On error, returns negative error code and sets errno:
> + *   - `-EINVAL`: Invalid parameters or ID mapping (duplicates, out-of-range)
> + *   - `-ENOMEM`: Memory allocation failure
> + */
> +LIBBPF_API int btf__permute(struct btf *btf, __u32 *id_map, __u32 id_map_cnt,
> +                           const struct btf_permute_opts *opts);
> +
>  struct btf_dump;
>
>  struct btf_dump_opts {
> diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map
> index 84fb90a016c9..d18fbcea7578 100644
> --- a/tools/lib/bpf/libbpf.map
> +++ b/tools/lib/bpf/libbpf.map
> @@ -453,4 +453,5 @@ LIBBPF_1.7.0 {
>                 bpf_map__exclusive_program;
>                 bpf_prog_assoc_struct_ops;
>                 bpf_program__assoc_struct_ops;
> +               btf__permute;
>  } LIBBPF_1.6.0;
> --
> 2.34.1
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ