Kernel modules are the only Linux subsystem where you can extend the running kernel without recompiling โ and also the easiest path to escalating from local to ring 0. Every USB device, every Bluetooth stack, every container runtime depends on the right modules being loaded; every CIS benchmark requires the wrong modules be blacklisted. This guide covers the day-to-day commands and the security-hardening that should be baked into every server build.
Inspecting what is loaded
lsmod # name, size, used-by count
lsmod | wc -l # raw module count
modinfo nf_tables # description, parameters, signature
cat /proc/modules # raw kernel view (lsmod parses this)
find /sys/module -maxdepth 1 -mindepth 1 -type d | wc -l
modinfo is essential before loading anything: it reveals the exact kernel API the module expects, its license (taint?), its parameters, and whether it is signed.
Loading and unloading
sudo modprobe dummy # load with dependencies
sudo modprobe dummy numdummies=4
sudo modprobe -r dummy # unload, fails if in use
sudo lsmod | grep dummy
sudo dmesg -T | tail # kernel feedback
Use modprobe, never insmod directly โ only modprobe resolves dependencies and writes to the kmod cache. Persist a load across reboots with a one-line file:
echo dummy | sudo tee /etc/modules-load.d/dummy.conf
echo 'options dummy numdummies=4' | sudo tee /etc/modprobe.d/dummy.conf
Blacklisting modules you do not want
Two mechanisms exist with different semantics:
# Blacklist: skip during automatic loading, but allow explicit modprobe
echo 'blacklist firewire-core' | sudo tee /etc/modprobe.d/blacklist-firewire.conf
# Hard-deny: refuse even explicit modprobe
echo 'install firewire-core /bin/true' | sudo tee /etc/modprobe.d/deny-firewire.conf
sudo update-initramfs -u # Debian/Ubuntu
sudo dracut --force # RHEL family
sudo reboot # confirm
The CIS benchmark recommends hard-deny for: cramfs, freevxfs, jffs2, hfs, hfsplus, squashfs, udf, usb-storage, dccp, sctp, rds, tipc, firewire-core. Each closes a specific lateral-movement or DMA-attack vector that almost no production server uses.
Signed modules and Secure Boot
Distributions ship with kernel module signing enforced under Secure Boot. Verify:
cat /proc/sys/kernel/modules_disabled # 1 = no further loading
mokutil --sb-state # SecureBoot enabled?
cat /sys/module/MODULE/taint # G = GPL clean, P = proprietary
dmesg | grep -E 'taint|signature'
To load a custom module under Secure Boot, sign it with a Machine Owner Key (MOK) and enroll the public key:
openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -nodes -days 36500 -subj "/CN=Local module signing/"
sudo /usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 MOK.priv MOK.der custom.ko
sudo mokutil --import MOK.der
sudo reboot # complete enrollment in firmware
Module parameters at runtime
Some parameters can be changed without unloading the module via sysfs:
ls /sys/module/i915/parameters/
echo 1 | sudo tee /sys/module/i915/parameters/enable_psr
Persist with a modprobe.d drop-in. For modules that cannot be unloaded (built into the kernel), the only way to change parameters is the kernel command line via GRUB.
Detecting unwanted modules at runtime
An attacker who already has root may insmod a kernel rootkit. Defenses:
- Lock down further loading after boot:
echo 1 > /proc/sys/kernel/modules_disabled. After this, no module can be loaded or unloaded until reboot. Useful on appliances; risky on general servers. - Audit module load events with auditd:
echo '-w /sbin/insmod -p x -k modules' | sudo tee -a /etc/audit/rules.d/modules.rules echo '-w /sbin/modprobe -p x -k modules' | sudo tee -a /etc/audit/rules.d/modules.rules sudo augenrules --load sudo ausearch -k modules -ts today - Snapshot
lsmodoutput at boot and diff hourly:lsmod | sort > /var/lib/modules-baseline.txt # at provisioning diff <(lsmod | sort) /var/lib/modules-baseline.txt
Troubleshooting load failures
When modprobe fails:
sudo modprobe -v failing_module # verbose dependency resolution
sudo dmesg -T | tail -50 # kernel rejection reason
sudo journalctl -kb 0 | grep -i failing_module
ldd /lib/modules/$(uname -r)/kernel/.../mod.ko 2>/dev/null
modinfo failing_module | grep -E 'depends|signature|vermagic'
The most common causes: vermagic mismatch (module compiled for a different kernel), missing firmware in /lib/firmware, or a missing dependency module that distribution packaging should have pulled in.
Common pitfalls
- Loading a module with
insmodinstead ofmodprobe; works once, vanishes after reboot, breaks dependency resolution. - Forgetting to rebuild initramfs after blacklist changes โ the unwanted module loads from the early ramdisk anyway.
- Blacklisting
usb-storageon a server, then later wondering why a USB stick mount fails (it is the point). - Using
install MODULE /bin/falseinstead of/bin/trueโ/bin/falseexits non-zero, polluting logs with cron-style noise.
Module hygiene is a five-minute audit per host that closes attack paths and surfaces hardware misconfigurations. Bake the blacklist into your golden image, alert on unexpected lsmod diffs, and you remove an entire category of post-exploitation tooling from your environment.