Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <mmaurer@google.com>
Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>

authored by

Matthew Maurer and committed by
Luis Chamberlain
d979e3df 837031e0

+37 -1
+37 -1
kernel/module/main.c
··· 2090 2090 } 2091 2091 2092 2092 /** 2093 - * elf_validity_cache_strtab() - Cache symbol string table 2093 + * elf_validity_cache_strtab() - Validate and cache symbol string table 2094 2094 * @info: Load info to read from and update. 2095 2095 * Must have &load_info->sechdrs and &load_info->secstrings populated. 2096 2096 * Must have &load_info->index populated. 2097 + * 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. 2097 2106 * 2098 2107 * Return: 0 on success, negative error code if a check failed. 2099 2108 */ 2100 2109 static int elf_validity_cache_strtab(struct load_info *info) 2101 2110 { 2102 2111 Elf_Shdr *str_shdr = &info->sechdrs[info->index.str]; 2112 + Elf_Shdr *sym_shdr = &info->sechdrs[info->index.sym]; 2103 2113 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 + } 2104 2140 2105 2141 info->strtab = strtab; 2106 2142 return 0;