Kernel Modules

Kernel modules extend the Linux kernel at runtime without rebooting. Device drivers, filesystems, network protocols — all can be loaded as modules when needed and unloaded when done. The kernel you boot is lean; modules add what's needed on demand. This is why Linux supports thousands of hardware devices without a monolithic kernel.

Managing Modules

# List loaded modules: lsmod # Module Size Used by # nvidia 10000000 35 # nvidia_uvm 100000 0 # ext4 1234567 1 # libcrc32c 12345 2 ext4,btrfs # Load a module: modprobe ext4 # loads with auto-dependencies insmod /path/to/mod.ko # load specific file, no auto-deps # Unload: modprobe -r ext4 # unload + unload unused dependencies rmmod ext4 # unload specific module (fails if in use) # Get module info: modinfo ext4 # filename: /lib/modules/6.1.0/kernel/fs/ext4/ext4.ko # description: Fourth Extended Filesystem # author: Remy Card, ... # license: GPL # depends: mbcache,jbd2 # parm: debug_wants_extra_isize:int # Module parameters: modprobe usbcore autosuspend=-1 # load with parameter echo -1 > /sys/module/usbcore/parameters/autosuspend # change live

Writing a Minimal Kernel Module

/* hello.c — minimal kernel module */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("TuteWorld"); MODULE_DESCRIPTION("Minimal hello world module"); static int __init hello_init(void) { printk(KERN_INFO "Hello, kernel world!\n"); return 0; /* 0 = success, negative = error */ } static void __exit hello_exit(void) { printk(KERN_INFO "Goodbye, kernel world!\n"); } module_init(hello_init); module_exit(hello_exit);
# Makefile: obj-m += hello.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean # Build and load: make sudo insmod hello.ko dmesg | tail -1 # [ 1234.567] Hello, kernel world! sudo rmmod hello dmesg | tail -1 # [ 2345.678] Goodbye, kernel world!

Module Parameters

/* module with parameters */ #include <linux/module.h> #include <linux/moduleparam.h> static int myval = 42; module_param(myval, int, 0644); MODULE_PARM_DESC(myval, "An integer parameter"); static char *mystr = "hello"; module_param(mystr, charp, 0644); MODULE_PARM_DESC(mystr, "A string parameter"); /* Load with custom values: */ /* insmod mymodule.ko myval=100 mystr="world" */ /* Read/write live values: */ /* cat /sys/module/mymodule/parameters/myval */ /* echo 200 > /sys/module/mymodule/parameters/myval */

Module Signing and Secure Boot

# Modules can be signed with a cryptographic key # Required when Secure Boot is active # Check if a module is signed: modinfo nvidia | grep sig # signer: NVIDIA corporation # sig_key: AA:BB:CC:... # sig_hashalgo: sha256 # Check if the kernel requires signed modules: cat /sys/kernel/security/lockdown # [integrity] = modules must be signed # Generate your own key (for custom modules): openssl req -new -x509 -newkey rsa:2048 \ -keyout MOK.priv -outform DER -out MOK.der \ -days 36500 -subj "/CN=MyModuleKey/" # Sign a module: /usr/src/linux-headers-$(uname -r)/scripts/sign-file \ sha256 MOK.priv MOK.der mymodule.ko # Enroll key in MOK database (requires reboot): mokutil --import MOK.der