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;