How to rebuild a single kernel module¶
If you have a patch for a specific kernel driver and want to test it quickly, you can rebuild just that module out-of-tree instead of rebuilding the entire kernel. This approach is significantly faster and is well suited for iterating on a driver fix.
Important
Modules built using this method are not intended for use in production. For managing kernel modules across kernel upgrades, consider using dkms(8) instead.
Prerequisites¶
Use this method when your patch is confined to the driver’s own sources.
If your patch changes shared kernel headers, Kconfig options, or the signature
of an exported symbol, the rebuilt module no longer matches the running kernel.
CONFIG_MODVERSIONS refuses to load a module whose exported symbol signatures
changed, but it does not detect structure layout changes inside headers. For
those changes, build and boot a complete kernel instead. See
How to build an Ubuntu Linux kernel.
The module is built against the running kernel version (uname -r) and works
only on that version. Installing a different kernel requires rebuilding the
module.
This guide supports Trusty Tahr and newer.
Install required packages¶
sudo apt update && \
sudo apt install -y linux-source build-essential linux-headers-$(uname -r)
Note
If you are developing against a custom kernel you will need to manually
install it’s headers using dpkg, rather than getting Ubuntu kernel headers
from apt.
Obtain and patch the kernel source¶
Install the kernel source package and extract it to your working directory:
sudo apt install -y linux-source
tar xjf /usr/src/linux-source-$(uname -r | cut -d- -f1).tar.bz2
Note
The tarball name uses the base kernel version (e.g. linux-source-6.8.0.tar.bz2),
not the full ABI version string reported by uname -r.
Apply your patch to the extracted source tree:
cd linux-source-$(uname -r | cut -d- -f1)
patch -p1 < /path/to/your.patch
Build the module¶
Build only the driver subdirectory containing your change. Replace
drivers/<path/to/driver> with the actual path relative to the kernel source
root (for example, drivers/net/ethernet/intel/e1000e):
make -C /lib/modules/$(uname -r)/build \
M=$PWD/drivers/<path/to/driver> modules
The compiled module file (<driver>.ko) will appear inside
drivers/<path/to/driver>/.
Load and test the module¶
Unload the old module if it is currently loaded, then load the new one:
sudo modprobe -r <driver>
sudo insmod drivers/<path/to/driver>/<driver>.ko
Important
On a system with Secure Boot enabled, loading an unsigned module will fail. Either test on a system with Secure Boot disabled, such as a virtual machine, or sign the module with an enrolled Machine Owner Key (MOK).
Confirm the module loaded successfully:
lsmod | grep <driver>
sudo dmesg | tail -20
Test and verify that your patch is working as intended.
To restore the module shipped with the kernel,
run sudo modprobe -r <driver> followed by sudo modprobe <driver>.
Note
Loading a module with insmod affects only the running system and will not
persist through reboots.
Make the module persist across reboots¶
To test the behaviour of a module at boot, install it into the updates
directory. depmod searches this directory ahead of the one holding the
module shipped with the kernel, so your build takes precedence without
modifying any file owned by a package:
sudo mkdir -p /lib/modules/$(uname -r)/updates
sudo cp drivers/<path/to/driver>/<driver>.ko /lib/modules/$(uname -r)/updates/
sudo depmod -a
modinfo -F filename <driver>
The path reported by modinfo must be the one under updates.
If the driver is in the initramfs, you need to rebuild that too:
lsinitramfs /boot/initrd.img-$(uname -r) | grep <driver>
sudo update-initramfs -u -k $(uname -r)
To remove the override, delete the file from updates, then rerun depmod, and
update-initramfs if you rebuilt the initramfs.
Note
The override applies only to the kernel version you installed it under. Installing a new kernel provides a new module tree, and your build is no longer used.