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 <ben.levinsky@amd.com>
This commit is contained in:
Ben Levinsky
2026-09-21 09:50:11 +02:00
committed by Arnaud Pouliquen
parent 08a45aca33
commit 28b0a020c6
+38 -2
View File
@@ -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;