BPF List
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Alan Maguire" <alan.maguire@oracle.com>
Cc: bpf@vger.kernel.org, linux-modules@vger.kernel.org
Subject: Re: [PATCH v2 bpf-next 03/18] libbpf: Support moving permuted BTF types into split BTF
Date: Tue, 01 Sep 2026 17:15:04 +0000	[thread overview]
Message-ID: <20260901171505.2A73F1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260901165757.801449-4-alan.maguire@oracle.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [High] If `btf_compact_strings()` fails, `btf__permute()` returns an error but leaves the BTF object in an irreversibly truncated and permuted state without updating the caller's `id_map`.
- [Low] LIBBPF-001 API rule violation: `btf_add_local_str` incorrectly uses `libbpf_err()` as an internal function, and `btf__add_str` fails to use it on its error return.

Pre-existing issues:
- [High] `btf__permute` completely corrupts base BTF permutations due to incorrect handling of `start_offs`, resulting in heap out-of-bounds accesses and total deletion of the VOID type.
--

commit 9de40ca1824ca5dbac1f65a763fe3a6beedba81f
Author: Alan Maguire <alan.maguire@oracle.com>

libbpf: Support moving permuted BTF types into split BTF
    
This commit extends btf__permute() with an optional transfer mode to move
specific permuted BTF types into a newly-created split BTF. It handles
remapping type IDs, migrating referenced strings, and compacting string
tables so that strings exclusive to the moved types reside only in the
split BTF.

> diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
> index 9449f6f50f18f..30f8c426d1453 100644
> --- a/tools/lib/bpf/btf.c
> +++ b/tools/lib/bpf/btf.c
> @@ -2147,16 +2147,9 @@ int btf__find_str(struct btf *btf, const char *s)
>   *   - > 0 offset into string section, on success;
>   *   - < 0, on error.
>   */
> -int btf__add_str(struct btf *btf, const char *s)
> +static int btf_add_local_str(struct btf *btf, const char *s)
>  {
> -	int off;
> -	int err;
> -
> -	if (btf->base_btf) {
> -		off = btf__find_str(btf->base_btf, s);
> -		if (off != -ENOENT)
> -			return off;
> -	}
> +	int off, err;
>  
>  	err = btf_ensure_modifiable(btf);
>  	if (err)
> @@ -2167,10 +2160,24 @@ int btf__add_str(struct btf *btf, const char *s)
>  		return libbpf_err(off);
        ^^^^^^^^^^^^^^^^^^^^^^

[Severity: Low]
Does the internal static function btf_add_local_str() incorrectly use the
libbpf_err() wrapper here, while the public API btf__add_str() below fails
to wrap its own error return?

>  
>  	btf->hdr.str_len = strset__data_size(btf->strs_set);
> +	btf->strs_deduped = false;
>  
>  	return btf->start_str_off + off;
>  }
>  
> +int btf__add_str(struct btf *btf, const char *s)
> +{
> +	int off;
> +
> +	if (btf->base_btf) {
> +		off = btf__find_str(btf->base_btf, s);
> +		if (off != -ENOENT)
> +			return off;
> +	}
> +
> +	return btf_add_local_str(btf, s);
> +}

[ ... ]

> @@ -6678,33 +6759,82 @@ int btf__permute(struct btf *btf, __u32 *id_map, __u32 id_map_cnt,
>  	if (err)
>  		goto done;
>  
> +	/*
> +	 * Build the inverse map: for each requested destination ID, record the
> +	 * original type ID that will occupy it. order_map is indexed by the
> +	 * destination ID relative to the first ID represented by id_map. The
> +	 * caller id_map maps old IDs to requested destinations, but BTF types
> +	 * must be emitted in destination-ID order; the inverse map supplies the
> +	 * old type to copy for each output slot without repeatedly searching
> +         * id_map.
> +         */
>  	for (i = start_offs; i < id_map_cnt; i++) {
> -		id = id_map[i];
> -		if (id < btf->start_id || id >= btf__type_cnt(btf)) {
> +		__u32 requested_id = new_id_map[i];
> +		__u32 order_idx;
> +
> +		if (btf_permute_id_is_transfer(requested_id)) {
> +			if (!transfer_btfp) {
> +				err = -EINVAL;
> +				goto done;
> +			}
> +			requested_id &= ~BTF_PERMUTE_ID_TRANSFER;
> +			nr_transfer++;
> +		}
> +		if (requested_id < btf->start_id || requested_id >= btf__type_cnt(btf)) {
>  			err = -EINVAL;
>  			goto done;
>  		}
> -		id -= btf->start_id - start_offs;
> +		order_idx = requested_id - btf->start_id + start_offs;
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

[Severity: High]
This is a pre-existing issue, but does the order_idx calculation go out of
bounds for base BTFs?

For a base BTF, btf->start_id is 0 and start_offs is 1. If requested_id
reaches id_map_cnt - 1 (the maximum valid ID), order_idx will become
id_map_cnt.

This would cause an out-of-bounds access when writing to order_map[order_idx]
below, since order_map is allocated with size id_map_cnt.

>  		/* cannot be mapped to the same ID */
> -		if (order_map[id]) {
> +		if (order_map[order_idx]) {
>  			err = -EINVAL;
>  			goto done;
>  		}
> -		order_map[id] = i + btf->start_id - start_offs;
> +		order_map[order_idx] = i + btf->start_id - start_offs;
> +	}

[ ... ]

> @@ -6729,18 +6916,58 @@ int btf__permute(struct btf *btf, __u32 *id_map, __u32 id_map_cnt,
>  			goto done;
>  	}
>  
> -	for (nt = new_types, i = 0; i < id_map_cnt - start_offs; i++) {
> +	/* Install the compacted parent types and rebuild their index. */
> +	for (nt = new_types, i = 0; i < nr_base_types; i++) {
>  		btf->type_offs[i] = nt - new_types;
>  		nt += btf_type_size(btf, nt);
>  	}
> -
> -	free(order_map);
>  	free(btf->types_data);
>  	btf->types_data = new_types;
> +	committed = true;
> +	btf_hdr_update_type_len(btf, nt - new_types);
> +	btf->nr_types = nr_base_types;
> +
> +	/*
> +	 * An important goal is to also transfer strings to the transfer
> +	 * BTF where they do not have duplicates in BTF. This is important
> +	 * for cases like inline BTF where inline function names could
> +	 * comprise a significant portion of the string table. The approach
> +	 * is to first compact the set of strings in the base now transfer
> +	 * is complete; this will remove unreferenced strings. Then
> +	 * local references in the transfer BTF have to be moved downwards
> +	 * based upon that compaction. Finally also compact transfer BTF
> +	 * references so that we replace duplicate references in split with
> +	 * base references where present.
> +	 *
> +	 * Once all this is done, we end up with transfer-only strings in
> +	 * transfer split BTF and shared strings in BTF. The result is
> +	 * a transfer BTF with a lot of transfer-only strings will not
> +	 * pollute the string table of the non-transfer BTF.
> +	 */
> +	if (transfer_btf) {
> +		err = btf_compact_strings(btf, btf_ext);
> +		if (err)
> +			goto done;
                ^^^^^^^^^

[Severity: High]
If btf_compact_strings() fails here, we return an error but the
btf->types_data replacement has already been committed. 

Does this leave the BTF object in an irreversibly corrupted state from the
caller's perspective, since id_map is not updated on the error path and the
transferred types are lost?

> +		err = btf_permute_rebase_split_strs(transfer_btf, old_str_off);
> +		if (err)
> +			goto done;
> +		err = btf_compact_strings(transfer_btf, NULL);
> +		if (err)
> +			goto done;
> +		*transfer_btfp = transfer_btf;
> +	}
> +
> +	/* On success return the final old-to-new type-ID map to the caller. */
> +	memcpy(id_map, new_id_map, id_map_cnt * sizeof(*id_map));
> +	free(new_id_map);
> +	free(order_map);
>  	return 0;
>  
>  done:
> +	free(new_id_map);
>  	free(order_map);
> -	free(new_types);
> +	if (!committed)
> +		free(new_types);
> +	btf__free(transfer_btf);
>  	return libbpf_err(err);
>  }

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

  reply	other threads:[~2026-09-01 17:15 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-01 16:57 [PATCH v2 bpf-next 00/18] Support inline functions in BTF Alan Maguire
2026-09-01 16:57 ` [PATCH v2 bpf-next 01/18] btf: Extend UAPI to support BTF location (inline site) info Alan Maguire
2026-09-01 17:17   ` sashiko-bot
2026-09-01 17:55   ` bot+bpf-ci
2026-09-01 16:57 ` [PATCH v2 bpf-next 02/18] libbpf: Add support for BTF kinds LOC[_PARAM|_PROTO|SEC] Alan Maguire
2026-09-01 17:11   ` sashiko-bot
2026-09-01 16:57 ` [PATCH v2 bpf-next 03/18] libbpf: Support moving permuted BTF types into split BTF Alan Maguire
2026-09-01 17:15   ` sashiko-bot [this message]
2026-09-01 18:14   ` bot+bpf-ci
2026-09-01 16:57 ` [PATCH v2 bpf-next 04/18] selftests/bpf: Test helper support for BTF_KIND_LOC[_PARAM|_PROTO|SEC] Alan Maguire
2026-09-01 17:06   ` sashiko-bot
2026-09-01 16:57 ` [PATCH v2 bpf-next 05/18] selftests/bpf: Add LOC_PARAM, LOC_PROTO, LOCSEC to field iter tests Alan Maguire
2026-09-01 16:57 ` [PATCH v2 bpf-next 06/18] selftests/bpf: Add LOC_PARAM, LOC_PROTO, LOCSEC to dedup split tests Alan Maguire
2026-09-01 17:55   ` bot+bpf-ci
2026-09-01 16:57 ` [PATCH v2 bpf-next 07/18] selftests/bpf: BTF distill tests to ensure LOC[_PARAM|_PROTO] add to split BTF Alan Maguire
2026-09-01 17:55   ` bot+bpf-ci
2026-09-01 16:57 ` [PATCH v2 bpf-next 08/18] selftests/bpf: Validate that btf__permute transfer works Alan Maguire
2026-09-01 17:16   ` sashiko-bot
2026-09-01 17:55   ` bot+bpf-ci
2026-09-01 16:57 ` [PATCH v2 bpf-next 09/18] bpftool: Handle multi-split BTF by supporting multiple base BTFs Alan Maguire
2026-09-01 17:13   ` sashiko-bot
2026-09-01 16:57 ` [PATCH v2 bpf-next 10/18] bpftool: Document support for multi-split BTF Alan Maguire
2026-09-01 17:12   ` sashiko-bot
2026-09-01 16:57 ` [PATCH v2 bpf-next 11/18] bpftool: Add ability to dump LOC_PARAM, LOC_PROTO and LOCSEC Alan Maguire
2026-09-01 17:16   ` sashiko-bot
2026-09-01 17:55   ` bot+bpf-ci
2026-09-01 16:57 ` [PATCH v2 bpf-next 12/18] resolve_btfids: Extract inline BTF Alan Maguire
2026-09-01 17:23   ` sashiko-bot
2026-09-01 16:57 ` [PATCH v2 bpf-next 13/18] kbuild: Add support for BTF inline information Alan Maguire
2026-09-01 17:55   ` bot+bpf-ci
2026-09-01 16:57 ` [PATCH v2 bpf-next 14/18] btf: Make vmlinux, module inline info available in /sys/kernel/btf Alan Maguire
2026-09-01 16:57 ` [PATCH v2 bpf-next 15/18] btf: Support CONFIG_DEBUG_INFO_BTF_INLINE=m Alan Maguire
2026-09-01 17:24   ` sashiko-bot
2026-09-01 16:57 ` [PATCH v2 bpf-next 16/18] btf: Relocate inline BTF for modules with distilled base BTF Alan Maguire
2026-09-01 17:29   ` sashiko-bot
2026-09-01 17:55   ` bot+bpf-ci
2026-09-01 16:57 ` [PATCH v2 bpf-next 17/18] selftests/bpf: Test BTF sysfs inline representations Alan Maguire
2026-09-01 17:22   ` sashiko-bot
2026-09-01 17:55   ` bot+bpf-ci
2026-09-01 16:57 ` [PATCH v2 bpf-next 18/18] selftests/bpf: Add a test verifying inline information Alan Maguire
2026-09-01 17:28   ` sashiko-bot
2026-09-01 17:55   ` bot+bpf-ci

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260901171505.2A73F1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=alan.maguire@oracle.com \
    --cc=bpf@vger.kernel.org \
    --cc=linux-modules@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox