From 28b0a020c633715d7b90341b3b9ec44277d030d4 Mon Sep 17 00:00:00 2001 From: Ben Levinsky Date: Mon, 1 Jun 2026 07:30:27 -0700 Subject: [PATCH] remoteproc: bound ELF section name lookups Make ELF section-name lookup validate sh_name before reading from the loaded section string table. Skip malformed section names whose sh_name offset is outside the table or whose string is not NUL-terminated within the remaining table bytes. Use bounded comparison for valid candidates so .resource_table lookup cannot read past the loaded string table. Signed-off-by: Ben Levinsky --- lib/remoteproc/elf_loader.c | 40 +++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/remoteproc/elf_loader.c b/lib/remoteproc/elf_loader.c index 2e6a265..e28599e 100644 --- a/lib/remoteproc/elf_loader.c +++ b/lib/remoteproc/elf_loader.c @@ -235,6 +235,35 @@ static int *elf_load_state(void *elf_info) } } +/** + * @brief Compare a section name with a bounded section string table entry. + * + * @param name Section name to match. + * @param name_table Loaded section string table. + * @param name_table_size Size of the loaded section string table. + * @param sh_name Offset of the candidate name in the string table. + * + * @return true if the name matches, otherwise false. + */ +static bool elf_section_name_matches(const char *name, const char *name_table, + size_t name_table_size, size_t sh_name) +{ + size_t name_len; + size_t remaining; + const char *candidate; + + if (sh_name >= name_table_size) + return false; + + remaining = name_table_size - sh_name; + name_len = strlen(name); + if (name_len >= remaining) + return false; + + candidate = name_table + sh_name; + return memcmp(name, candidate, name_len + 1) == 0; +} + static void elf_parse_segment(void *elf_info, const void *elf_phdr, unsigned int *p_type, size_t *p_offset, metal_phys_addr_t *p_vaddr, @@ -303,6 +332,7 @@ static void *elf_get_section_from_name(void *elf_info, const char *name) { unsigned int i; const char *name_table; + size_t name_table_size; if (elf_is_64(elf_info) == 0) { struct elf32_info *einfo = elf_info; @@ -310,10 +340,13 @@ static void *elf_get_section_from_name(void *elf_info, const char *name) Elf32_Shdr *shdr = einfo->shdrs; name_table = einfo->shstrtab; + name_table_size = einfo->shstrtab_size; if (!shdr || !name_table) return NULL; for (i = 0; i < ehdr->e_shnum; i++, shdr++) { - if (strcmp(name, name_table + shdr->sh_name)) + if (!elf_section_name_matches(name, name_table, + name_table_size, + shdr->sh_name)) continue; else return shdr; @@ -324,10 +357,13 @@ static void *elf_get_section_from_name(void *elf_info, const char *name) Elf64_Shdr *shdr = einfo->shdrs; name_table = einfo->shstrtab; + name_table_size = einfo->shstrtab_size; if (!shdr || !name_table) return NULL; for (i = 0; i < ehdr->e_shnum; i++, shdr++) { - if (strcmp(name, name_table + shdr->sh_name)) + if (!elf_section_name_matches(name, name_table, + name_table_size, + shdr->sh_name)) continue; else return shdr;