mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-26 11:41:35 +01:00
Less converstaion
This commit is contained in:
13
README.md
13
README.md
@@ -12,14 +12,13 @@ Run one command, get a QEMU Buildroot BusyBox virtual machine built from source
|
|||||||
1. [X11](x11.md)
|
1. [X11](x11.md)
|
||||||
1. [gdbserver](gdbserver.md)
|
1. [gdbserver](gdbserver.md)
|
||||||
1. [Count boot instructions](count-boot-instructions.md)
|
1. [Count boot instructions](count-boot-instructions.md)
|
||||||
1. [Record and replay](record-and-replay.md)
|
|
||||||
1. [Hello host](hello_host/)
|
1. [Hello host](hello_host/)
|
||||||
1. Conversation
|
|
||||||
1. [Introduction](introduction.md)
|
|
||||||
1. [Build](build.md)
|
|
||||||
1. [kmod](kmod.md)
|
|
||||||
1. [vermagic](vermagic.md)
|
|
||||||
1. [ftrace](ftrace.md)
|
1. [ftrace](ftrace.md)
|
||||||
1. [Device tree](device-tree.md)
|
1. [Device tree](device-tree.md)
|
||||||
|
1. [modprobe](modprobe.md)
|
||||||
|
1. Failed action
|
||||||
|
1. [Record and replay](record-and-replay.md)
|
||||||
1. [GEM5](gem5.md)
|
1. [GEM5](gem5.md)
|
||||||
1. [Bibliography](bibliography.md)
|
1. Conversation
|
||||||
|
1. [kmod](kmod.md)
|
||||||
|
1. [Bibliography](bibliography.md)
|
||||||
|
|||||||
31
build.md
31
build.md
@@ -1,31 +0,0 @@
|
|||||||
# Build
|
|
||||||
|
|
||||||
The module building system.
|
|
||||||
|
|
||||||
Explained at: <https://www.kernel.org/doc/Documentation/kbuild/modules.txt>
|
|
||||||
|
|
||||||
Full method: get the kernel, build it to a directory `$KDIR`, and then run:
|
|
||||||
|
|
||||||
make -C "$KDIR" M="$(PWD)" modules
|
|
||||||
|
|
||||||
Quick method: no need for a full build, just:
|
|
||||||
|
|
||||||
make modules_prepare
|
|
||||||
|
|
||||||
but you lose some functionality. TODO: module insert on host then fails with:
|
|
||||||
|
|
||||||
insmod: ERROR: could not insert module hello.ko: Invalid module format
|
|
||||||
|
|
||||||
even though kernel tree was checked out to match the host.
|
|
||||||
|
|
||||||
Using your distro's kernel version:
|
|
||||||
|
|
||||||
/lib/modules/$(uname -r)/build
|
|
||||||
|
|
||||||
## includes
|
|
||||||
|
|
||||||
Header files come from the same directory as the makefile: `/lib/modules/$(uname -r)/build`.
|
|
||||||
|
|
||||||
TODO how is that different from: `/usr/src/linux-headers-$(uname -r)/` ?
|
|
||||||
|
|
||||||
Those come directly from the kernel source tree.
|
|
||||||
@@ -236,31 +236,6 @@ or on host:
|
|||||||
|
|
||||||
cat buildroot/output.*~/build/linux-custom/.config
|
cat buildroot/output.*~/build/linux-custom/.config
|
||||||
|
|
||||||
## insmod alternatives
|
|
||||||
|
|
||||||
If you are feeling fancy, you can also insert modules with:
|
|
||||||
|
|
||||||
modprobe hello
|
|
||||||
|
|
||||||
This method also deals with module dependencies, which we almost don't use to make examples simpler:
|
|
||||||
|
|
||||||
- <https://askubuntu.com/questions/20070/whats-the-difference-between-insmod-and-modprobe>
|
|
||||||
- <https://stackoverflow.com/questions/22891705/whats-the-difference-between-insmod-and-modprobe>
|
|
||||||
|
|
||||||
`modprobe` searches for modules under:
|
|
||||||
|
|
||||||
ls /lib/modules/*/extra/
|
|
||||||
|
|
||||||
Kernel modules built from the Linux mainline tree with `CONFIG_SOME_MOD=m`, are automatically available with `modprobe`, e.g.:
|
|
||||||
|
|
||||||
modprobe dummy-irq
|
|
||||||
|
|
||||||
If you are feeling raw, you can use our own minimal:
|
|
||||||
|
|
||||||
/myinsmod.out /hello.ko
|
|
||||||
|
|
||||||
which demonstrates the C module API: <https://stackoverflow.com/questions/5947286/how-can-linux-kernel-modules-be-loaded-from-c-code/38606527#38606527>
|
|
||||||
|
|
||||||
## QEMU GUI is unresponsive
|
## QEMU GUI is unresponsive
|
||||||
|
|
||||||
Sometimes in Ubuntu 14.04, after the QEMU SDL GUI starts, it does not get updated after keyboard strokes, and there are artifacts like disappearing text.
|
Sometimes in Ubuntu 14.04, after the QEMU SDL GUI starts, it does not get updated after keyboard strokes, and there are artifacts like disappearing text.
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
# Introduction
|
|
||||||
|
|
||||||
There are things which are hard to do from regular user programs such as directly talking to hardware.
|
|
||||||
|
|
||||||
Some operations can be done via system calls, but if you want flexibility and speed, using the kernel ring is fundamental
|
|
||||||
|
|
||||||
However:
|
|
||||||
|
|
||||||
- it would be very complicated to recompile the kernel and reboot every time you make some modification
|
|
||||||
- the kernel would be huge if it were to support all possible hardware
|
|
||||||
|
|
||||||
Modules overcome those two problems exactly because they can be loaded into the kernel *while it is running* and use symbols that the kernel chooses to export TODO which
|
|
||||||
|
|
||||||
It then runs in the same address space as the kernel and with the same permissions as the kernel (basically do anything)
|
|
||||||
|
|
||||||
Compiled modules are special object files that have a `.ko` extension instead of `.o` they also contain module specific metadata
|
|
||||||
|
|
||||||
Device drivers (programs that enables the computer to talk to hardware) are one specific type of kernel modules
|
|
||||||
|
|
||||||
Two devices can map to the same hardware!
|
|
||||||
|
|
||||||
## Configuration files
|
|
||||||
|
|
||||||
If file it gets read, if dir, all files in dir get read:
|
|
||||||
|
|
||||||
sudo ls /etc/modprobe.d
|
|
||||||
sudo ls /etc/modprobe.conf
|
|
||||||
|
|
||||||
Modules loaded at boot:
|
|
||||||
|
|
||||||
sudo cat /etc/modules
|
|
||||||
|
|
||||||
## Hardware communication
|
|
||||||
|
|
||||||
Talking to hardware always comes down to writing bytes in specific registers at a given memory addresses.
|
|
||||||
|
|
||||||
Some processors implement a single address space for memory and other hardware devices, and others do not.
|
|
||||||
|
|
||||||
However, since x86 is the most popular and it separates address spaces, every architecture must at least mimic this separation.
|
|
||||||
|
|
||||||
On x86, the following specialized instructions exist for port IO:
|
|
||||||
|
|
||||||
- `IN`: Read from a port
|
|
||||||
- `OUT`: Write to a port
|
|
||||||
- `INS/INSB`: Input string from port/Input byte string from port
|
|
||||||
- `INS/INSW`: Input string from port/Input word string from port
|
|
||||||
- `INS/INSD`: Input string from port/Input `doubleword` string from port
|
|
||||||
- `OUTS/OUTSB`: Output string to port/Output byte string to port
|
|
||||||
- `OUTS/OUTSW`: Output string to port/Output word string to port
|
|
||||||
- `OUTS/OUTSD`: Output string to port/Output `doubleword` string to port
|
|
||||||
|
|
||||||
However, you should avoid using those instructions directly in your device driver code since Linux functions abstract over multiple architectures (when possible) making your code more portable.
|
|
||||||
|
|
||||||
Those instructions cannot be used from an user space program since the kernel prevents those from accessing hardware directly.
|
|
||||||
|
|
||||||
The memory space for non-memory locations is called I/O ports or I/O space.
|
|
||||||
|
|
||||||
To use a port, you must first reserve it. To see who reserved what:
|
|
||||||
|
|
||||||
sudo cat /proc/ioports
|
|
||||||
@@ -6,7 +6,10 @@
|
|||||||
1. [hello](hello.c)
|
1. [hello](hello.c)
|
||||||
1. [hello2](hello2.c)
|
1. [hello2](hello2.c)
|
||||||
1. [panic](panic.c)
|
1. [panic](panic.c)
|
||||||
1. [params](params.c)
|
1. Module utils
|
||||||
|
1. [params](params.c)
|
||||||
|
1. [vermagic](vermagic.c)
|
||||||
|
1. [vermagic_fail](vermagic_fail.c)
|
||||||
1. Pseudo filesystems
|
1. Pseudo filesystems
|
||||||
1. [debugfs](debugfs.c)
|
1. [debugfs](debugfs.c)
|
||||||
1. [procfs](procfs.c)
|
1. [procfs](procfs.c)
|
||||||
|
|||||||
21
kernel_module/vermagic.c
Normal file
21
kernel_module/vermagic.c
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
insmod /vermagic.ko
|
||||||
|
# => 4.9.6 SMP mod_unload modversions
|
||||||
|
TODO how to get the vermagic from running kernel from userland? <https://lists.kernelnewbies.org/pipermail/kernelnewbies/2012-October/006306.html>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/vermagic.h>
|
||||||
|
|
||||||
|
static int myinit(void)
|
||||||
|
{
|
||||||
|
pr_info(VERMAGIC_STRING "\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void myexit(void) {}
|
||||||
|
|
||||||
|
module_init(myinit)
|
||||||
|
module_exit(myexit)
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
30
kernel_module/vermagic_fail.c
Normal file
30
kernel_module/vermagic_fail.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
insmod /vermagic_fail.ko
|
||||||
|
# => insmod: can't insert '/vermagic_fail.ko': invalid module format
|
||||||
|
|
||||||
|
modinfo /vermagic_fail.ko | grep vermagic
|
||||||
|
# => vermagic: asdfqwer
|
||||||
|
# => vermagic: 4.9.6 SMP mod_unload modversions
|
||||||
|
|
||||||
|
kmod `modprobe` has a flag to skip the check:
|
||||||
|
|
||||||
|
--force-modversion
|
||||||
|
|
||||||
|
Looks like it just strips `modversion` information from the module before loading, and then the kernel skips the check.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
|
||||||
|
static int myinit(void)
|
||||||
|
{
|
||||||
|
pr_info("vermagic_fail\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void myexit(void) {}
|
||||||
|
|
||||||
|
module_init(myinit)
|
||||||
|
module_exit(myexit)
|
||||||
|
MODULE_INFO(vermagic, "asdfqwer");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
119
kmod.md
119
kmod.md
@@ -1,114 +1,35 @@
|
|||||||
# kmod
|
# kmod
|
||||||
|
|
||||||
Multi-call executable that implements: `lsmod`, `insmod`, `rmmod`, and other tools.
|
Multi-call executable that implements: `lsmod`, `insmod`, `rmmod`, and other tools on desktop distros such as Ubuntu 16.04, where e.g.:
|
||||||
|
|
||||||
BusyBox also implements its own version of those executables.
|
ls -l /bin/lsmod
|
||||||
|
|
||||||
Source: <https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git>
|
gives:
|
||||||
|
|
||||||
The other tools are just symlinks to it.
|
lrwxrwxrwx 1 root root 4 Jul 25 15:35 /bin/lsmod -> kmod
|
||||||
|
|
||||||
|
and:
|
||||||
|
|
||||||
|
dpkg -l | grep -Ei
|
||||||
|
|
||||||
|
contains:
|
||||||
|
|
||||||
|
ii kmod 22-1ubuntu5 amd64 tools for managing Linux kernel modules
|
||||||
|
|
||||||
|
BusyBox also implements its own version of those executables. There are some differences.
|
||||||
|
|
||||||
|
Buildroot also has a kmod package, but we are not using it since BusyBox' version is good enough so far.
|
||||||
|
|
||||||
|
This page will only describe features that differ from kmod to the BusyBox implementation.
|
||||||
|
|
||||||
|
Source code: <https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git>
|
||||||
|
|
||||||
## module-init-tools
|
## module-init-tools
|
||||||
|
|
||||||
Name of a predecessor set of tools.
|
Name of a predecessor set of tools.
|
||||||
|
|
||||||
## package version
|
|
||||||
|
|
||||||
From any of the commands, `--version`:
|
|
||||||
|
|
||||||
modinfo --version
|
|
||||||
|
|
||||||
Package that provides utilities
|
|
||||||
|
|
||||||
## lsmod
|
|
||||||
|
|
||||||
List loaded kernel modules.
|
|
||||||
|
|
||||||
Info is taken from `/proc/modules`
|
|
||||||
|
|
||||||
lsmod
|
|
||||||
|
|
||||||
Sample output:
|
|
||||||
|
|
||||||
cfg80211 175574 2 rtlwifi,mac80211
|
|
||||||
^^^^^^^^ ^^^^^^ ^ ^^^^^^^,^^^^^^^^
|
|
||||||
1 2 3 4 5
|
|
||||||
|
|
||||||
1. Name.
|
|
||||||
|
|
||||||
2. Size.
|
|
||||||
|
|
||||||
3. Number of running instances.
|
|
||||||
|
|
||||||
If negative, TODO
|
|
||||||
|
|
||||||
4. Depends on 1.
|
|
||||||
|
|
||||||
5. Depends on 2.
|
|
||||||
|
|
||||||
To get more info:
|
|
||||||
|
|
||||||
cat /proc/modules
|
|
||||||
|
|
||||||
Also contains two more columns:
|
|
||||||
|
|
||||||
- status: Live, Loading or Unloading
|
|
||||||
- memory offset: 0x129b0000
|
|
||||||
|
|
||||||
## modinfo
|
|
||||||
|
|
||||||
Get info about a module by filename or by module name:
|
|
||||||
|
|
||||||
modinfo ./a.ko
|
|
||||||
modinfo a
|
|
||||||
|
|
||||||
TODO must take a `.ko` file?
|
|
||||||
|
|
||||||
## insmod
|
|
||||||
|
|
||||||
sudo insmod hello.ko
|
|
||||||
|
|
||||||
Loads the module.
|
|
||||||
|
|
||||||
Does not check for dependencies.
|
|
||||||
|
|
||||||
## rmmod
|
|
||||||
|
|
||||||
Remove a module. Takes either the module name or the `.ko` file:
|
|
||||||
|
|
||||||
sudo rmmod hello
|
|
||||||
sudo rmmod ./hello.ko
|
|
||||||
|
|
||||||
## modprobe
|
## modprobe
|
||||||
|
|
||||||
Vs `insmod`:
|
|
||||||
|
|
||||||
- <https://askubuntu.com/questions/20070/whats-the-difference-between-insmod-and-modprobe>
|
|
||||||
- <https://stackoverflow.com/questions/22891705/whats-the-difference-between-insmod-and-modprobe>
|
|
||||||
|
|
||||||
List available modules relative path to `/lib/modules/$KERNEL_VERSION/`:
|
|
||||||
|
|
||||||
sudo modprobe -l
|
|
||||||
|
|
||||||
Load the module:
|
|
||||||
|
|
||||||
sudo modprobe $m
|
|
||||||
|
|
||||||
Checks for dependencies.
|
|
||||||
|
|
||||||
Load module under different name to avoid conflicts:
|
Load module under different name to avoid conflicts:
|
||||||
|
|
||||||
sudo modprobe vmhgfs -o vm_hgfs
|
sudo modprobe vmhgfs -o vm_hgfs
|
||||||
|
|
||||||
Remove module:
|
|
||||||
|
|
||||||
sudo modprobe -r $m
|
|
||||||
|
|
||||||
Check if dependencies are OK:
|
|
||||||
|
|
||||||
sudo depmod -a
|
|
||||||
|
|
||||||
Get info about given `.ko` module file:
|
|
||||||
|
|
||||||
m=a
|
|
||||||
sudo rmmod $m
|
|
||||||
|
|||||||
35
modprobe.md
Normal file
35
modprobe.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# modprobe
|
||||||
|
|
||||||
|
If you are feeling fancy, you can also insert modules with:
|
||||||
|
|
||||||
|
modprobe dep2
|
||||||
|
lsmod
|
||||||
|
# dep and dep2
|
||||||
|
|
||||||
|
This method also deals with module dependencies, which we almost don't use to make examples simpler:
|
||||||
|
|
||||||
|
- <https://askubuntu.com/questions/20070/whats-the-difference-between-insmod-and-modprobe>
|
||||||
|
- <https://stackoverflow.com/questions/22891705/whats-the-difference-between-insmod-and-modprobe>
|
||||||
|
|
||||||
|
Removal also removes required modules that have zero usage count:
|
||||||
|
|
||||||
|
modprobe -r dep2
|
||||||
|
lsmod
|
||||||
|
# Nothing.
|
||||||
|
|
||||||
|
but it can't know if you actually insmodded them separately or not:
|
||||||
|
|
||||||
|
modprobe dep
|
||||||
|
modprobe dep2
|
||||||
|
modprobe -r dep2
|
||||||
|
# Nothing.
|
||||||
|
|
||||||
|
so it is a bit risky.
|
||||||
|
|
||||||
|
`modprobe` searches for modules under:
|
||||||
|
|
||||||
|
ls /lib/modules/*/extra/
|
||||||
|
|
||||||
|
Kernel modules built from the Linux mainline tree with `CONFIG_SOME_MOD=m`, are automatically available with `modprobe`, e.g.:
|
||||||
|
|
||||||
|
modprobe dummy-irq
|
||||||
27
vermagic.md
27
vermagic.md
@@ -1,27 +0,0 @@
|
|||||||
# vermagic
|
|
||||||
|
|
||||||
If the module does not match that of the kernel, `insmod` is unhappy and fails.
|
|
||||||
|
|
||||||
Get it from kernel module:
|
|
||||||
|
|
||||||
modinfo mymod.ko
|
|
||||||
|
|
||||||
Override it on module source:
|
|
||||||
|
|
||||||
MODULE_INFO(vermagic, "newver");
|
|
||||||
|
|
||||||
On the Linux kernel 4.9.6, it is defined under `include/linux/vermagic.h`:
|
|
||||||
|
|
||||||
#define VERMAGIC_STRING \
|
|
||||||
UTS_RELEASE " " \
|
|
||||||
MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \
|
|
||||||
MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS \
|
|
||||||
MODULE_ARCH_VERMAGIC
|
|
||||||
|
|
||||||
TODO can you get it from running kernel from userland? <https://lists.kernelnewbies.org/pipermail/kernelnewbies/2012-October/006306.html>
|
|
||||||
|
|
||||||
Desktop `modprobe` has a flag to skip the check:
|
|
||||||
|
|
||||||
`--force-modversion`
|
|
||||||
|
|
||||||
Looks like it just strips `modversion` information from the module, and then the kernel skips the check.
|
|
||||||
Reference in New Issue
Block a user