FROMGIT: module: Additional validation in elf_validity_cache_strtab
Validate properties of the strtab that are depended on elsewhere, but were previously unchecked: * String table nonempty (offset 0 is valid) * String table has a leading NUL (offset 0 corresponds to "") * String table is NUL terminated (strfoo functions won't run out of the table while reading). * All symbols names are inbounds of the string table. Change-Id: I986b77fe9de77226c271dee528e44edd8a2d5cee Signed-off-by: Matthew Maurer <mmaurer@google.com> Reviewed-by: Sami Tolvanen <samitolvanen@google.com> Signed-off-by: Luis Chamberlain <mcgrof@kernel.org> (cherry picked from commit d979e3dffa93c9284f244ef64f7a68042c2f8b80 kernel/git/modules/linux.git modules-next) Bug: 347787665
This commit is contained in:
committed by
Matthias Männich
parent
de4c6d5b31
commit
e9f2fa03d3
+37
-1
@@ -2126,17 +2126,53 @@ static int elf_validity_cache_index(struct load_info *info, int flags)
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_validity_cache_strtab() - Cache symbol string table
|
||||
* elf_validity_cache_strtab() - Validate and cache symbol string table
|
||||
* @info: Load info to read from and update.
|
||||
* Must have &load_info->sechdrs and &load_info->secstrings populated.
|
||||
* Must have &load_info->index populated.
|
||||
*
|
||||
* Checks:
|
||||
*
|
||||
* * The string table is not empty.
|
||||
* * The string table starts and ends with NUL (required by ELF spec).
|
||||
* * Every &Elf_Sym->st_name offset in the symbol table is inbounds of the
|
||||
* string table.
|
||||
*
|
||||
* And caches the pointer as &load_info->strtab in @info.
|
||||
*
|
||||
* Return: 0 on success, negative error code if a check failed.
|
||||
*/
|
||||
static int elf_validity_cache_strtab(struct load_info *info)
|
||||
{
|
||||
Elf_Shdr *str_shdr = &info->sechdrs[info->index.str];
|
||||
Elf_Shdr *sym_shdr = &info->sechdrs[info->index.sym];
|
||||
char *strtab = (char *)info->hdr + str_shdr->sh_offset;
|
||||
Elf_Sym *syms = (void *)info->hdr + sym_shdr->sh_offset;
|
||||
int i;
|
||||
|
||||
if (str_shdr->sh_size == 0) {
|
||||
pr_err("empty symbol string table\n");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
if (strtab[0] != '\0') {
|
||||
pr_err("symbol string table missing leading NUL\n");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
if (strtab[str_shdr->sh_size - 1] != '\0') {
|
||||
pr_err("symbol string table isn't NUL terminated\n");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that we know strtab is correctly structured, check symbol
|
||||
* starts are inbounds before they're used later.
|
||||
*/
|
||||
for (i = 0; i < sym_shdr->sh_size / sizeof(*syms); i++) {
|
||||
if (syms[i].st_name >= str_shdr->sh_size) {
|
||||
pr_err("symbol name out of bounds in string table");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
info->strtab = strtab;
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user