It must be verified that the symbol name offsets point into the string table, not outside of it. Signed-off-by: Tobias Stoeckmann <tobias@xxxxxxxxxxxxxx> --- Proof of Concept: 1. Create "poc.sh" ``` cat > poc.sh << EOF #!/bin/sh # Sets an illegal symbol name offset in supplied uncompressed module # usage: ./poc file.ko MODULE="$1" BASE=$(readelf -S $MODULE | grep '\.symtab' | awk '{ print $5 }') if [ $(getconf LONG_BIT) = '64' ] then OFF=24 else OFF=16 fi ADDR=$(python -c "print(int(0x$BASE) + $OFF)") echo -n 'AAAA' | dd bs=1 count=4 of=$MODULE seek=$ADDR conv=notrunc echo $ADDR EOF ``` 2. Choose a module which works for your system (adjust if compressed) ``` cp $(find /lib/modules/$(uname -r) |grep ko$ | head -n 1) poc.ko ``` 3. Modify module ``` sh poc.sh poc.ko ``` 4. Try to insert ``` insmod poc.ko ``` In dmesg, you can see lines like: ``` BUG: unable to handle page fault for address: ffff9802022d6f81 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 100000067 P4D 100000067 PUD 0 --- kernel/module/main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/kernel/module/main.c b/kernel/module/main.c index 9c5b373a7..c926960ae 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -1688,6 +1688,7 @@ static int elf_validity_cache_copy(struct load_info *info, int flags) { unsigned int i; Elf_Shdr *shdr, *strhdr; + Elf_Sym *sym; int err; unsigned int num_mod_secs = 0, mod_idx; unsigned int num_info_secs = 0, info_idx; @@ -1859,6 +1860,17 @@ static int elf_validity_cache_copy(struct load_info *info, int flags) goto no_exec; } + /* Symbol names must point into string table. */ + shdr = &info->sechdrs[info->index.sym]; + sym = (void *)info->hdr + shdr->sh_offset; + for (i = 1; i < shdr->sh_size / sizeof(Elf_Sym); i++) { + if (sym[i].st_name >= strhdr->sh_size) { + pr_err("module %s: illegal symbol name offset encountered\n", + info->name ?: "(missing .modinfo section or name field)"); + goto no_exec; + } + } + /* * The ".gnu.linkonce.this_module" ELF section is special. It is * what modpost uses to refer to __this_module and let's use rely -- 2.47.0