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: Fix kernel panic when a symbol st_shndx is out of bounds

The module loader doesn't check for bounds of the ELF section index in
simplify_symbols():

for (i = 1; i < symsec->sh_size / sizeof(Elf_Sym); i++) {
const char *name = info->strtab + sym[i].st_name;

switch (sym[i].st_shndx) {
case SHN_COMMON:

[...]

default:
/* Divert to percpu allocation if a percpu var. */
if (sym[i].st_shndx == info->index.pcpu)
secbase = (unsigned long)mod_percpu(mod);
else
/** HERE --> **/ secbase = info->sechdrs[sym[i].st_shndx].sh_addr;
sym[i].st_value += secbase;
break;
}
}

A symbol with an out-of-bounds st_shndx value, for example 0xffff
(known as SHN_XINDEX or SHN_HIRESERVE), may cause a kernel panic:

BUG: unable to handle page fault for address: ...
RIP: 0010:simplify_symbols+0x2b2/0x480
...
Kernel panic - not syncing: Fatal exception

This can happen when module ELF is legitimately using SHN_XINDEX or
when it is corrupted.

Add a bounds check in simplify_symbols() to validate that st_shndx is
within the valid range before using it.

This issue was discovered due to a bug in llvm-objcopy, see relevant
discussion for details [1].

[1] https://lore.kernel.org/linux-modules/20251224005752.201911-1-ihor.solodrai@linux.dev/

Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
Reviewed-by: Daniel Gomez <da.gomez@samsung.com>
Reviewed-by: Petr Pavlu <petr.pavlu@suse.com>
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>

authored by

Ihor Solodrai and committed by
Sami Tolvanen
f9d69d5e 8d597ba6

+7
+7
kernel/module/main.c
··· 1568 1568 break; 1569 1569 1570 1570 default: 1571 + if (sym[i].st_shndx >= info->hdr->e_shnum) { 1572 + pr_err("%s: Symbol %s has an invalid section index %u (max %u)\n", 1573 + mod->name, name, sym[i].st_shndx, info->hdr->e_shnum - 1); 1574 + ret = -ENOEXEC; 1575 + break; 1576 + } 1577 + 1571 1578 /* Divert to percpu allocation if a percpu var. */ 1572 1579 if (sym[i].st_shndx == info->index.pcpu) 1573 1580 secbase = (unsigned long)mod_percpu(mod);