[PATCH 13/31] btf_encoder: Fix early cleanup crashes in btf_encoder__new/delete
Arnaldo Carvalho de Melo <[email protected]> Wed, 29 Jul 2026 16:07:13 -0300
| Newsgroups | org.kernel.vger.dwarves,org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
From: Arnaldo Carvalho de Melo <[email protected]> Fix three issues in btf_encoder initialization and cleanup: 1. INIT_LIST_HEAD(&encoder->elf_functions_list) was done after two goto out_delete paths (strdup and btf__new failures). Since the encoder is zalloc'd, elf_functions_list.next is NULL, so btf_encoder__delete() → elf_functions_list__clear() → list_for_each_safe dereferences NULL. Move the INIT_LIST_HEAD to the start. 2. btf_encoder__delete() iterates secinfo[] unconditionally, but if the calloc for secinfo fails, the pointer is NULL while seccnt is already set, causing a NULL dereference. Add a NULL guard. 3. Add NULL check for elf_strptr() return value before strcmp() in btf_encoder__write_elf(), preventing a crash on malformed ELF files. Before: NULL deref on strdup failure + secinfo alloc failure + bad ELF After: clean error paths in all cases Fixes: 99e78ff34f8171f9 ("btf_encoder: Introduce elf_functions_list") Reported-by: Sashiko:gemini-3-1-pro-preview Assisted-by: Claude:claude-sonnet-4-5 Signed-off-by: Arnaldo Carvalho de Melo <[email protected]> --- btf_encoder.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/btf_encoder.c b/btf_encoder.c index 0fbd7e3420b0457f..5c12e79f5ef648ba 100644 --- a/btf_encoder.c +++ b/btf_encoder.c @@ -2029,7 +2029,7 @@ static int btf_encoder__write_elf(struct btf_encoder *encoder, const struct btf if (shdr == NULL) continue; char *secname = elf_strptr(elf, strndx, shdr->sh_name); - if (strcmp(secname, btf_secname) == 0) { + if (secname != NULL && strcmp(secname, btf_secname) == 0) { btf_data = elf_getdata(scn, btf_data); break; } @@ -2780,6 +2780,7 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam struct elf_functions *funcs = NULL; if (encoder) { + INIT_LIST_HEAD(&encoder->elf_functions_list); encoder->cu = cu; encoder->raw_output = detached_filename != NULL; encoder->source_filename = strdup(cu->filename); @@ -2818,7 +2819,6 @@ struct btf_encoder *btf_encoder__new(struct cu *cu, const char *detached_filenam if (conf_load->encode_btf_global_vars) encoder->encode_vars |= BTF_VAR_GLOBAL; - INIT_LIST_HEAD(&encoder->elf_functions_list); funcs = btf_encoder__elf_functions(encoder); if (!funcs) goto out_delete; @@ -2912,9 +2912,11 @@ void btf_encoder__delete(struct btf_encoder *encoder) if (encoder == NULL) return; - for (shndx = 0; shndx < encoder->seccnt; shndx++) - __gobuffer__delete(&encoder->secinfo[shndx].secinfo); - free(encoder->secinfo); + if (encoder->secinfo) { + for (shndx = 0; shndx < encoder->seccnt; shndx++) + __gobuffer__delete(&encoder->secinfo[shndx].secinfo); + free(encoder->secinfo); + } zfree(&encoder->filename); zfree(&encoder->source_filename); btf__free(encoder->btf); -- 2.55.0