On Thu, Jun 19, 2025 at 3:14 PM Adin Scannell <adin@xxxxxxxxxxx> wrote: > > The `name` field in `obj->externs` points into the BTF data at load time. > However, some functions may invalidate this after loading (e.g. > `bpf_map__set_value_size`), which results in pointers into freed memory and > undefined behavior. > > The simplest solution is to simply `strdup` these strings, similar to the > `essent_name`, and free them at the same time. > > Signed-off-by: Adin Scannell <adin@xxxxxxxxxxx> > --- > tools/lib/bpf/libbpf.c | 8 +++++--- > 1 file changed, 5 insertions(+), 3 deletions(-) > > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c > index 6445165a24f2..5adf2b68adb3 100644 > --- a/tools/lib/bpf/libbpf.c > +++ b/tools/lib/bpf/libbpf.c > @@ -597,7 +597,7 @@ struct extern_desc { > int sym_idx; > int btf_id; > int sec_btf_id; > - const char *name; > + char *name; > char *essent_name; > bool is_set; > bool is_weak; > @@ -4259,7 +4259,7 @@ static int bpf_object__collect_externs(struct bpf_object *obj) > return ext->btf_id; > } > t = btf__type_by_id(obj->btf, ext->btf_id); > - ext->name = btf__name_by_offset(obj->btf, t->name_off); > + ext->name = strdup(btf__name_by_offset(obj->btf, t->name_off)); > ext->sym_idx = i; > ext->is_weak = ELF64_ST_BIND(sym->st_info) == STB_WEAK; > > @@ -9138,8 +9138,10 @@ void bpf_object__close(struct bpf_object *obj) > zfree(&obj->btf_custom_path); > zfree(&obj->kconfig); > > - for (i = 0; i < obj->nr_extern; i++) > + for (i = 0; i < obj->nr_extern; i++) { > + zfree(&obj->externs[i].name); > zfree(&obj->externs[i].essent_name); > + } Good catch! It's certainly a footgun that obj->btf->... will be reallocated during bpf_map__set_value_size(). Probably this commit caused this issue: Fixes: 9d0a23313b1a ("libbpf: Add capability for resizing datasec maps")