Skip to content

Commit d45ceac

Browse files
committed
0
0 parents  commit d45ceac

File tree

9 files changed

+318
-0
lines changed

9 files changed

+318
-0
lines changed

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
*.cmd
2+
*.ko
3+
*.mod.c
4+
*.o
5+
*.out
6+
*.tmp
7+
.tmp_versions
8+
Module.symvers
9+
modules.order

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Linux Kernel Module Cheat
2+
3+
1. [Introduction](introduction.md)
4+
1. [Build](build.md)
5+
1. [kmod](kmod.md)
6+
1. Examples
7+
1. [Host](host/)

build.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Build
2+
3+
The module building system.
4+
5+
Kernel modules are built using a makefile located at:
6+
7+
/lib/modules/$(uname -r)/build
8+
9+
## includes
10+
11+
Header files come from the same directory as the makefile: `/lib/modules/$(uname -r)/build`.
12+
13+
TODO how is that different from: `/usr/src/linux-headers-$(uname -r)/` ?
14+
15+
Those come directly from the kernel source tree.

host/Makefile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
OUT_EXT := .ko
2+
OBJ_EXT := .o
3+
RUN := hello
4+
RUN_EXT := $(RUN)$(OUT_EXT)
5+
6+
obj-m += hello.o
7+
ccflags-y := -Wno-declaration-after-statement -std=gnu99
8+
9+
.PHONY: clean ins log rm run my-ins
10+
11+
all: $(RUN_EXT) ins_rm_mod.out
12+
13+
hello.ko: hello.c
14+
make -C /lib/modules/$(shell uname -r)/build M="$(PWD)" modules
15+
16+
clean:
17+
make -C /lib/modules/$(shell uname -r)/build M="$(PWD)" clean
18+
rm -f *.out
19+
20+
ins: all
21+
sudo insmod '$(RUN_EXT)'
22+
23+
log:
24+
dmesg
25+
26+
rm:
27+
if lsmod | grep -Eq '^$(RUN) '; then sudo rmmod '$(RUN_EXT)'; fi
28+
29+
ins_rm_mod.out: ins_rm_mod.c
30+
gcc -Wall -std=gnu99 -o '$@' '$<'
31+
32+
ins_rm_run: ins_rm_mod.out $(RUN_EXT)
33+
sudo ./ins_rm_mod.out

host/README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Host
2+
3+
Simple things that can be demonstrated by inserting a module into the currently running host. Tested on Ubuntu 16.04.
4+
5+
1. [hello](hello.c)
6+
1. [ins_rm_mod.c](ins_rm_mod.c)
7+
8+
## Rationale
9+
10+
This method easier to setup, but it is not recommended for development, as:
11+
12+
- it may break your system.
13+
- you can't control which kernel version to use
14+
15+
Use VMs instead.
16+
17+
## Usage
18+
19+
We only use it for super simple examples.
20+
21+
Build, insert and remove a hello world module:
22+
23+
make ins
24+
make rm
25+
make log
26+
27+
The last lines of the log should contain:
28+
29+
init_module
30+
cleanup_module
31+
32+
Insert and remove a module from a C program:
33+
34+
make ins_rm_run

host/hello.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <linux/module.h>
2+
#include <linux/kernel.h>
3+
4+
int init_module(void)
5+
{
6+
printk(KERN_INFO "init_module\n");
7+
return 0;
8+
}
9+
10+
void cleanup_module(void)
11+
{
12+
printk(KERN_INFO "cleanup_module\n");
13+
}

host/ins_rm_mod.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
http://stackoverflow.com/questions/5947286/how-can-linux-kernel-modules-be-loaded-from-c-code/38606527#38606527
3+
*/
4+
5+
#define _GNU_SOURCE
6+
#include <assert.h>
7+
#include <fcntl.h>
8+
#include <stdio.h>
9+
#include <sys/stat.h>
10+
#include <sys/syscall.h>
11+
#include <sys/types.h>
12+
#include <unistd.h>
13+
#include <stdlib.h>
14+
15+
#define init_module(mod, len, opts) syscall(__NR_init_module, mod, len, opts)
16+
#define delete_module(name, flags) syscall(__NR_delete_module, name, flags)
17+
18+
int main(void) {
19+
int fd = open("hello.ko", O_RDONLY);
20+
struct stat st;
21+
fstat(fd, &st);
22+
size_t image_size = st.st_size;
23+
void *image = malloc(image_size);
24+
read(fd, image, image_size);
25+
close(fd);
26+
if (init_module(image, image_size, "") != 0) {
27+
perror("init_module");
28+
return EXIT_FAILURE;
29+
}
30+
free(image);
31+
if (delete_module("hello", O_NONBLOCK) != 0) {
32+
perror("delete_modul");
33+
return EXIT_FAILURE;
34+
}
35+
return EXIT_SUCCESS;
36+
}

introduction.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Introduction
2+
3+
There are things which are hard to do from regular user programs such as directly talking to hardware.
4+
5+
Some operations can be done via system calls, but if you want flexibility and speed, using the kernel ring is fundamental
6+
7+
However:
8+
9+
- it would be very complicated to recompile the kernel and reboot every time you make some modification
10+
- the kernel would be huge if it were to support all possible hardware
11+
12+
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
13+
14+
It then runs in the same address space as the kernel and with the same permissions as the kernel (basically do anything)
15+
16+
Compiled modules are special object files that have a `.ko` extension instead of `.o` they also contain module specific metadata
17+
18+
Device drivers (programs that enables the computer to talk to hardware) are one specific type of kernel modules
19+
20+
Two devices can map to the same hardware!
21+
22+
## Stable kernel interface
23+
24+
Kernel modules can use any internal interface of the kernel, although some are more visible than others.
25+
26+
But there is no stable kernel API for modules: if you don't add your driver to the kernel tree, it can break any time: <https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/stable_api_nonsense.txt?id=v4.0>
27+
28+
## Configuration files
29+
30+
If file it gets read, if dir, all files in dir get read:
31+
32+
sudo ls /etc/modprobe.d
33+
sudo ls /etc/modprobe.conf
34+
35+
Modules loaded at boot:
36+
37+
sudo cat /etc/modules
38+
39+
## Hardware communication
40+
41+
Talking to hardware always comes down to writing bytes in specific registers at a given memory addresses.
42+
43+
Some processors implement a single address space for memory and other hardware devices, and others do not.
44+
45+
However, since x86 is the most popular and it separates address spaces, every architecture must at least mimic this separation.
46+
47+
On x86, the following specialized instructions exist for port IO:
48+
49+
- `IN`: Read from a port
50+
- `OUT`: Write to a port
51+
- `INS/INSB`: Input string from port/Input byte string from port
52+
- `INS/INSW`: Input string from port/Input word string from port
53+
- `INS/INSD`: Input string from port/Input `doubleword` string from port
54+
- `OUTS/OUTSB`: Output string to port/Output byte string to port
55+
- `OUTS/OUTSW`: Output string to port/Output word string to port
56+
- `OUTS/OUTSD`: Output string to port/Output `doubleword` string to port
57+
58+
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.
59+
60+
Those instructions cannot be used from an user space program since the kernel prevents those from accessing hardware directly.
61+
62+
The memory space for non-memory locations is called I/O ports or I/O space.
63+
64+
To use a port, you must first reserve it. To see who reserved what:
65+
66+
sudo cat /proc/ioports

kmod.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# kmod
2+
3+
Implements `lsmod`, `insmod`, `rmmod`, and other tools.
4+
5+
The other tools are just symlinks to it.
6+
7+
## module-init-tools
8+
9+
Name of a predecessor set of tools.
10+
11+
## package version
12+
13+
From any of the commands, `--version`:
14+
15+
modinfo --version
16+
17+
Package that provides utilities
18+
19+
## lsmod
20+
21+
List loaded kernel modules.
22+
23+
Info is taken from `/proc/modules`
24+
25+
lsmod
26+
27+
Sample output:
28+
29+
cfg80211 175574 2 rtlwifi,mac80211
30+
^^^^^^^^ ^^^^^^ ^ ^^^^^^^,^^^^^^^^
31+
1 2 3 4 5
32+
33+
1. Name.
34+
35+
2. Size.
36+
37+
3. Number of running instances.
38+
39+
If negative, TODO
40+
41+
4. Depends on 1.
42+
43+
5. Depends on 2.
44+
45+
To get more info:
46+
47+
cat /proc/modules
48+
49+
Also contains two more columns:
50+
51+
- status: Live, Loading or Unloading
52+
- memory offset: 0x129b0000
53+
54+
## modinfo
55+
56+
Get info about a module by filename or by module name:
57+
58+
modinfo ./a.ko
59+
modinfo a
60+
61+
TODO must take a `.ko` file?
62+
63+
## insmod
64+
65+
sudo insmod hello.ko
66+
67+
Loads the module.
68+
69+
Does not check for dependencies.
70+
71+
## rmmod
72+
73+
Remove a module. Takes either the module name or the `.ko` file:
74+
75+
sudo rmmod hello
76+
sudo rmmod ./hello.ko
77+
78+
## modprobe
79+
80+
List available modules relative path to `/lib/modules/VERSION/`:
81+
82+
sudo modprobe -l
83+
84+
Load the module:
85+
86+
sudo modprobe $m
87+
88+
Checks for dependencies.
89+
90+
Load module under different name to avoid conflicts:
91+
92+
sudo modprobe vmhgfs -o vm_hgfs
93+
94+
Remove module:
95+
96+
sudo modprobe -r $m
97+
98+
Check if dependencies are OK:
99+
100+
sudo depmod -a
101+
102+
Get info about given `.ko` module file:
103+
104+
m=a
105+
sudo rmmod $m

0 commit comments

Comments
 (0)