Build Kernel Module from a Customized Kernel
Published:
In recent projects, we need to hack on Linux Kernel with various customization on multiple architectures. However, common distros like Fedora/Debian/Centos will not provide compatible kernel development headers (staffs under /lib/modules/$version) required by building kernel modules.
For example, if we compile a kernel module without a compatible kernel development header, it complains:
make -C /lib/modules/6.1.11/build M=... modules
make[1]: *** /lib/modules/6.1.11/build: No such file or directory. Stop.
make: *** [Makefile:6: all] Error 2
To fix this issue, we have to build ourselves a kernel development header from the source. It took some time to find a solution.
Build Kernel Module Preparation
First, we should get the exact version of the source code and the same configuration (.config) with your customized kernel. Then, run modules_prepare
target.
cd /path/to/linux-6.1.11
make modules_prepare
Note that modules_prepare
target will not generate Module.symvers
, which contains a list of exported symbols from a kernel build. Module.symvers
is crucial for module versioning but is not necessary for an experimental kernel module. Run a full kernel build if we need Module.symvers
.
Copy this kernel directory to /usr/src
and rename.
(sudo) cp /path/to/linux-6.1.11 /usr/src/linux-headers-6.1.11
Link it to /lib/modules/6.1.11/build
.
(sudo) ln -s /usr/src/linux-headers-6.1.11 /lib/modules/6.1.11/build
Done!
Test with a Kernel Module
We test the self-built kernel development header with an example kernel module (hello.c) from The Linux Kernel Module Programming Guide
Source code:
/*
* hello.c - The simplest kernel module.
*/
#include <linux/kernel.h> /* Needed for pr_info() */
#include <linux/module.h> /* Needed by all modules */
int init_module(void)
{
pr_info("Hello world.\n");
/* A non 0 return means init_module failed; module can't be loaded. */
return 0;
}
void cleanup_module(void)
{
pr_info("Goodbye world.\n");
}
MODULE_LICENSE("GPL");
Building script:
obj-m += hello.o
PWD := $(CURDIR)
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 test:
$ make
$ (sudo) insmod hello.ko
[15394.319943] hello: loading out-of-tree module taints kernel.
[15394.371244] Hello world.
$ (sudo) rmmod hello
[15436.280762] Goodbye world.
Cheers!