From 9abe2c42ecab6c86b54838d2d645ca2e10204606 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Mon, 2 Nov 2026 18:58:39 +0000 Subject: [PATCH] libbpf: Fix use-after-free in btf__add_type 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. Make all the bases of dst modifiable before the pointer is taken. This bug is triggered by the sharing of BTF bases between src and dst, as introduced by the resolve_btfids changes to build inline BTF. Fixes: cf91a7db92c6 ("resolve_btfids: Build separate main and inline BTF objects") Reported-by: Nathan Chancellor Signed-off-by: Alexei Starovoitov Signed-off-by: Alan Maguire Signed-off-by: Alexei Starovoitov Tested-by: Alan Maguire Link: https://patch.msgid.link/20261102185839.1190122-1-almagui@kernel.org --- tools/lib/bpf/btf.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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 @@ -2222,6 +2222,7 @@ struct btf_pipe { static int btf_rewrite_str(struct btf_pipe *p, __u32 *str_off) { + struct btf *base; long mapped_off; int off, err; @@ -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)); if (off < 0) return off;