lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ