[PATCH] module: check symbol name offsets

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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






[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux