Skip to content

Commit d979e3d

Browse files
maurermcgrof
authored andcommitted
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. Signed-off-by: Matthew Maurer <[email protected]> Reviewed-by: Sami Tolvanen <[email protected]> Signed-off-by: Luis Chamberlain <[email protected]>
1 parent 837031e commit d979e3d

File tree

1 file changed

+37
-1
lines changed

1 file changed

+37
-1
lines changed

kernel/module/main.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2090,17 +2090,53 @@ static int elf_validity_cache_index(struct load_info *info, int flags)
20902090
}
20912091

20922092
/**
2093-
* elf_validity_cache_strtab() - Cache symbol string table
2093+
* elf_validity_cache_strtab() - Validate and cache symbol string table
20942094
* @info: Load info to read from and update.
20952095
* Must have &load_info->sechdrs and &load_info->secstrings populated.
20962096
* Must have &load_info->index populated.
20972097
*
2098+
* Checks:
2099+
*
2100+
* * The string table is not empty.
2101+
* * The string table starts and ends with NUL (required by ELF spec).
2102+
* * Every &Elf_Sym->st_name offset in the symbol table is inbounds of the
2103+
* string table.
2104+
*
2105+
* And caches the pointer as &load_info->strtab in @info.
2106+
*
20982107
* Return: 0 on success, negative error code if a check failed.
20992108
*/
21002109
static int elf_validity_cache_strtab(struct load_info *info)
21012110
{
21022111
Elf_Shdr *str_shdr = &info->sechdrs[info->index.str];
2112+
Elf_Shdr *sym_shdr = &info->sechdrs[info->index.sym];
21032113
char *strtab = (char *)info->hdr + str_shdr->sh_offset;
2114+
Elf_Sym *syms = (void *)info->hdr + sym_shdr->sh_offset;
2115+
int i;
2116+
2117+
if (str_shdr->sh_size == 0) {
2118+
pr_err("empty symbol string table\n");
2119+
return -ENOEXEC;
2120+
}
2121+
if (strtab[0] != '\0') {
2122+
pr_err("symbol string table missing leading NUL\n");
2123+
return -ENOEXEC;
2124+
}
2125+
if (strtab[str_shdr->sh_size - 1] != '\0') {
2126+
pr_err("symbol string table isn't NUL terminated\n");
2127+
return -ENOEXEC;
2128+
}
2129+
2130+
/*
2131+
* Now that we know strtab is correctly structured, check symbol
2132+
* starts are inbounds before they're used later.
2133+
*/
2134+
for (i = 0; i < sym_shdr->sh_size / sizeof(*syms); i++) {
2135+
if (syms[i].st_name >= str_shdr->sh_size) {
2136+
pr_err("symbol name out of bounds in string table");
2137+
return -ENOEXEC;
2138+
}
2139+
}
21042140

21052141
info->strtab = strtab;
21062142
return 0;

0 commit comments

Comments
 (0)