This commit is contained in:
Andriy Petrov 2024-04-17 14:26:30 +02:00
parent 08ca3702af
commit 02efdca8d0

View File

@ -1,17 +1,17 @@
The process of [kernel modules compilation](https://www.kernel.org/doc/html/v5.6/kbuild/modules.html) depends heavily on accessibility of header files provided by kernel. There are exist no guarantees on ABI compatibility even between minor kernel versions. This is [deliberate design choice](https://github.com/torvalds/linux/blob/v4.9/Documentation/stable_api_nonsense.txt) made by kernel developers. Kernel module compilation *depends* on kernel headers.
Kernel module [compilation](https://www.kernel.org/doc/html/v5.6/kbuild/modules.html) *depends* on kernel headers. This is a [deliberate design choice](https://github.com/torvalds/linux/blob/v4.9/Documentation/stable_api_nonsense.txt) made by kernel developers. As result, there is no even a slight guarantee of an ABI compatibility even between minor kernel versions.
> But what to do if, for the variety of reasons, for the kernel you are interest in, headers are unavailable?
The code in this repo focuses on Android, but most of the information and techniques discussed here can be easily applied to the generic Linux kernel as well.
The code in this repo gives an answer to this question. It focuses on Android, but most of the information and techniques discussed here can be easily applied to the generic Linux kernel as well.
# ELF symbols stealing
The main idea, is to use Android NDK to compile generic Linux kernel module. And embed it with ELF symbols collected from some existing kernel module (see `/vendor/lib/modules/*.ko`). In such a way, that the LKM loader would be able to recognise and resolve all necessary dependencies and definitions.
The main idea, is to use Android NDK to compile generic a Linux kernel module with pre-embed ELF symbols collected from some existing kernel module. See, for example, `/vendor/lib/modules/*.ko` for a possible donor. The idea is to provide just enough information, so that the LKM loader would be able to recognise and resolve all the necessary dependencies and default, and in the end to load our kernel agnostic module.
## PLT section
This part is pretty straight forward, we simply have to define a few ELF symbols, that Android LKM is expecting to find within *normal* module. We are going to really on [compiler keyword](https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Variable-Attributes.html) `__attribute__` for this.
This part is pretty straight forward, we simply have to define a few ELF symbols, that Android LKM is expecting to find within *normal* module. We are going to use `__attribute__` [compiler keyword](https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Variable-Attributes.html) for this.
```c
// insmod error: module PLT section(s) missing
@ -48,7 +48,7 @@ objdump -s -j .modinfo $KMODULE
00d0 00
```
This ELF section essentially is collection of 'TAG=VALUE' entries separated by NULL character '\0'. The most important part is `vermagic`, since loader is using it do identify which kernel headers were used for module compilation.
This ELF section essentially is a collection of 'TAG=VALUE' entries separated by NULL character '\0'. The most important part is `vermagic`, since the loader is using it do identify which kernel headers were used for the module compilation and compares it against his own `vermagic` variable. They must be identical.
```bash
cat /proc/version
@ -131,6 +131,21 @@ In order for module to use any externally declared symbol module must:
```
2. Add another entry to the `__versions` section
```c
char __attribute__((section("__versions"))) ____versions[] = {
/* module_layout */ // <<-- MUST BE PROVIDED
0xe8, 0xd6, 0xfc, 0x68, 0x00, 0x00, 0x00, 0x00, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x6c,
0x61, 0x79, 0x6f, 0x75, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* printk */
0xa1, 0x58, 0x55, 0x98, 0x00, 0x00, 0x00, 0x00, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x6b, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
```
# Misc commands