[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <2hhrajjoxixnkhtlhhqzjxki4iuhr362345wgrmg6uzbfhlupo@hgbjsb5wizir>
Date: Sat, 19 Oct 2024 16:15:32 +0200
From: Tobias Stoeckmann <tobias@...eckmann.org>
To: mcgrof@...nel.org
Cc: linux-modules@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH] module: check symbol name offsets
It must be verified that the symbol name offsets point into the
string table, not outside of it.
Signed-off-by: Tobias Stoeckmann <tobias@...eckmann.org>
---
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
Powered by blists - more mailing lists