Understand why and how to write a simple kernel module
What is a kernel module?
Why write a kernel module?
Important considerations
How to load and unload
Building up an example
What is the difference between a kernel module and a device driver?
Definition: a kernel module is a chunk of code that can be loaded into the kernel at runtime
Modify the kernel without re-compiling or even rebooting
Built as a *.ko file
*.ko
ELF: Executable and linkable format
file on a module object file
file
executable by itself, nor is it synchronous
safe, since all code runs directly in the kernel
a driver, rather it is a mechanism by which to implement a driver
Keep the main kernel small
Quicker development process
Distribution flexibility
What could we use modules for?
Device drivers
Filesystem support e.g. ext4, xfs, and nfs
ext4
xfs
nfs
Network protocol support such as ipv6
ipv6
Cryptographic protocols like sha256 and aes
sha256
aes
Virtualization module, e.g. KVM
lsmod
ls /lib/modules/$(uname -r)
/proc/modules
module_name: The name of the loaded module
size: Memory size used by the module (in bytes)
used_count: The number of processes using this module
dependencies: List of other modules that this module depends on (comma-separated)
state: Module state (Live, Loading, or Unloading)
offset: The kernel memory offset where the module is loaded
Toggled in the compilation configuration
look at .config/menuconfig tri-state options
make help | grep all.*config
No main(), but init() runs on module load
main()
init()
Define exit() to be able to unload
exit()
Other entry points depend on module purpose
probe()
struct file_operations
Modules must be compiled for specific kernel version
May access kernel symbol table
May export it's own symbols
EXPORT_SYMBOL
The tree in question: kernel repository
Build a module during kernel build process
Take a look at how new modules can be added to kernel build system
Build modules as standalone units
Loading an out-of-tree (oot) module can mark the kernel as "tainted"
To install dependencies to build modules for current version:
sudo dnf install kernel-devel-$(uname -r)
3 main utilities:
insmod
rmmod
modprobe
insmod takes a path to a *.ko file
modprobe take a module name in the /lib/modules/$(uname -r) subtree
/lib/modules/$(uname -r)
rmmod and modprobe -r takes the name of a loaded module
modprobe -r
init_module(2) loads a struct module into the kernel
init_module(2)
struct module
finit_module(2) does the same thing with a file descriptor
finit_module(2)
delete_module(2) removes a module given it's name
delete_module(2)
ikconfig in the minimal distro: in-tree
See: kernel/configs.c
kernel/configs.c
Built as the module in the minimal linux demo rootfs
Show inserting/removing in different ways
Show /proc/module address in /proc/kallsyms
/proc/module
/proc/kallsyms
Show bits in /sys/module
/sys/module
The most minimal module possible
MODULE_LICENSE("GPL")
minimal but removable module
print on enter and exit: A "Hello world" module
Take a look at include/linux/module.h
Why and how to write a simple kernel module
A Linux kernel module is an ELF object that can be loaded into a running kernel
Modularization can reduce the kernel binary size and attack surface
Use kernel modules to implement device drivers, filesystems, network protocols, and more
Multiple entry points, including init() which is run at load time
Build using makefile provided by the kernel repository
Load and unload using modprobe, insmod, and rmmod