* Re: [PATCH bpf] libbpf: Fix use-after-free in btf__add_type
2026-11-02 18:58 [PATCH bpf] libbpf: Fix use-after-free in btf__add_type Alan Maguire
@ 2026-11-02 19:43 ` bot+bpf-ci
2026-11-02 22:50 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: bot+bpf-ci @ 2026-11-02 19:43 UTC (permalink / raw)
To: almagui, ast
Cc: daniel, andrii, eddyz87, memxor, martin.lau, song, yonghong.song,
jolsa, emil, ihor.solodrai, bpf, nathan, almagui, ast, andrii,
daniel, martin.lau, eddyz87, yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 3453 bytes --]
> libbpf: Fix use-after-free in btf__add_type
TL;DR: The fix in btf_rewrite_str() may still leave a dangling string pointer
(use-after-free) in btf__add_str() for mid-string offsets in a shared base
BTF; likely not hit by in-tree BTF, so a gap in the fix.
> diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
> index d2ff6f5d6d5b..95c31803e722 100644
> --- a/tools/lib/bpf/btf.c
> +++ b/tools/lib/bpf/btf.c
[ ... ]
> @@ -2234,6 +2235,19 @@ static int btf_rewrite_str(struct btf_pipe *p, __u32 *str_off)
> return 0;
> }
>
> + /*
> + * btf__add_str() first looks the string up in the base BTFs of dst,
> + * which makes each of them modifiable and frees its raw data. If src
> + * shares a base with dst and the string lives in that base, the
> + * pointer taken below would be left dangling. So make the bases
> + * modifiable before the pointer is taken.
> + */
> + for (base = p->dst->base_btf; base; base = base->base_btf) {
> + err = btf_ensure_modifiable(base);
> + if (err)
> + return err;
> + }
> +
> off = btf__add_str(p->dst, btf__str_by_offset(p->src, *str_off));
Can the pointer passed to btf__add_str() here still end up dangling when
*str_off points into the middle of a string in the shared base (a suffix
such as "bar" in "foobar")?
A base that was not modifiable before the loop gets its strset built by
strset__new(), which sets strs_data_cap equal to strs_data_len. The first
lookup in that set therefore reallocs the buffer:
btf__add_str(dst, s)
btf__find_str(base, s)
strset__find_str(base->strs_set, s)
strset_str_append()
strset_add_str_mem() -> libbpf_add_mem() -> realloc(strs_data)
strset_str_append() fixes up its own local copy of s, but the s held by
btf__add_str() is not updated.
Only string starts are hashed in the base, so a suffix offset can miss. In
that case btf__find_str() returns -ENOENT and btf__add_str() carries on with
the original, now stale, pointer:
if (btf->base_btf) {
off = btf__find_str(btf->base_btf, s);
if (off != -ENOENT)
return off;
}
...
off = strset__add_str(btf->strs_set, s);
strset__add_str() -> strset_str_append() then does strlen(s) and memcpy()
from the freed buffer. The relocation check in strset_str_append() does not
help there, since s is not inside dst's buffer.
btf_validate_str() only checks that btf__str_by_offset() is non-NULL, so such
offsets are accepted. This needs src and dst to share a base (or src to be a
base of dst), a base that was not modifiable yet, a first lookup on it with
a mid-string offset, and a realloc that moves the block.
BTF from pahole, LLVM and btf__dedup() does not use suffix offsets, so the
in-tree resolve_btfids flow is probably not affected, and the code before
this patch crashed on the same input. This looks like a gap left by the fix
rather than new breakage.
Would it be more robust to leave *str_off unchanged for offsets that fall
inside a base shared by src and dst, the way btf__add_btf() does with its
"*str_off < src_btf->start_str_off" check ("don't remap strings from shared
base BTF")? The offset is already valid in dst, and no pointer into the base
would be taken at all.
---
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/41508558529
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH bpf] libbpf: Fix use-after-free in btf__add_type
2026-11-02 18:58 [PATCH bpf] libbpf: Fix use-after-free in btf__add_type Alan Maguire
2026-11-02 19:43 ` bot+bpf-ci
@ 2026-11-02 22:50 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-11-02 22:50 UTC (permalink / raw)
To: Alan Maguire
Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, bpf, nathan
Hello:
This patch was applied to bpf/bpf.git (master)
by Alexei Starovoitov <ast@kernel.org>:
On Mon, 2 Nov 2026 18:58:39 +0000 you wrote:
> From: Alexei Starovoitov <ast@kernel.org>
>
> For every string btf_rewrite_str() does:
>
> off = btf__add_str(p->dst, btf__str_by_offset(p->src, *str_off));
>
> When the string belongs to the base, the pointer goes into the raw data
> of the base. btf__add_str() looks the string up in the base first,
> btf__find_str() calls btf_ensure_modifiable() on the base, and that
> frees the raw data. Then strset__find_str() reads the freed string.
>
> [...]
Here is the summary with links:
- [bpf] libbpf: Fix use-after-free in btf__add_type
https://git.kernel.org/bpf/bpf/c/9abe2c42ecab
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 3+ messages in thread