Linux Kernel Module Management

Linux kernel modules are loadable code components that extend kernel functionality for hardware drivers, filesystems, and network protocols without requiring a kernel reboot. This guide covers managing modules with modprobe, configuring module parameters, blacklisting problematic modules, using DKMS for out-of-tree modules, and troubleshooting kernel module issues.

Prerequisites

  • Linux system (Ubuntu 20.04+, CentOS/Rocky 8+)
  • Root access
  • Kernel headers matching your running kernel
  • Basic understanding of kernel versions and hardware drivers

Listing and Inspecting Modules

# List all currently loaded modules
lsmod

# Filter for a specific module
lsmod | grep nvidia
lsmod | grep usb

# Get detailed info about a module
modinfo ext4
modinfo nvme

# Key fields in modinfo output:
# filename: path to the .ko file
# description: module description
# license: GPL, proprietary, etc.
# depends: other modules this one requires
# parm: configurable parameters
# Find the .ko file for a module
find /lib/modules/$(uname -r) -name "*.ko" | grep drm
find /lib/modules/$(uname -r) -name "e1000e*"

# List all available modules (installed but not necessarily loaded)
find /lib/modules/$(uname -r) -name "*.ko*" | wc -l

# Check module dependencies
modinfo --field=depends e1000e

# View full dependency tree
modprobe --show-depends e1000e

Check module signing status:

# View module signature info
modinfo --field=sig_hashalgo nvme
modinfo --field=signer nvme

# Check if kernel enforces module signing
cat /sys/module/module/parameters/sig_enforce
# 0 = not enforced, 1 = enforced (Secure Boot typically sets this)

Loading and Unloading Modules

# Load a module (handles dependencies automatically)
sudo modprobe e1000e

# Load with verbose output
sudo modprobe -v e1000e

# Simulate loading (test without actually loading)
sudo modprobe --dry-run e1000e

# Unload a module
sudo modprobe -r e1000e

# Unload forcefully (can cause instability)
sudo modprobe -rf e1000e

# Alternative: insmod (no dependency resolution)
sudo insmod /lib/modules/$(uname -r)/kernel/drivers/net/ethernet/intel/e1000e/e1000e.ko

# Alternative: rmmod (no dependency check)
sudo rmmod e1000e

Force reload a module (unload and reload):

# Check if module can be removed (UsedBy count = 0)
lsmod | grep e1000e
# e1000e   153600  0    <- 0 = not in use

# If in use, find what's using it
lsmod | awk '/^e1000e/ {print $4}'

# Reload
sudo modprobe -r e1000e && sudo modprobe e1000e

Module Parameters

Many modules accept parameters to adjust behavior:

# View available parameters for a module
modinfo --field=parm <module>

# Example: view usbcore parameters
modinfo --field=parm usbcore

# View current parameter values for loaded module
ls /sys/module/usbcore/parameters/
cat /sys/module/usbcore/parameters/autosuspend

# Change a parameter at runtime (while module is loaded)
echo 5 | sudo tee /sys/module/usbcore/parameters/autosuspend

# Load module with specific parameters
sudo modprobe usbcore autosuspend=2

# Example: load iwlwifi WiFi module with power management disabled
sudo modprobe iwlwifi power_save=0

Persistent Module Loading

Modules loaded with modprobe are not persistent across reboots. Use these methods:

Auto-load on boot via /etc/modules-load.d/:

# Load a module automatically at boot
sudo tee /etc/modules-load.d/mymodule.conf << 'EOF'
# Load these modules at boot
br_netfilter
overlay
ip_conntrack
EOF

# Verify it will load
sudo systemctl restart systemd-modules-load.service
sudo systemctl status systemd-modules-load.service
lsmod | grep br_netfilter

Persistent module parameters via /etc/modprobe.d/:

# Set parameters that apply every time a module loads
sudo tee /etc/modprobe.d/iwlwifi.conf << 'EOF'
# Disable WiFi power management
options iwlwifi power_save=0

# Disable 11n mode (compatibility fix)
options iwlwifi 11n_disable=1
EOF

# Reload module to apply
sudo modprobe -r iwlwifi && sudo modprobe iwlwifi

# Verify parameter
cat /sys/module/iwlwifi/parameters/power_save

Ubuntu: /etc/modules file (legacy, still works):

sudo nano /etc/modules
# Add one module per line:
# loop
# v4l2loopback

Blacklisting Modules

Prevent specific modules from loading—useful for disabling problematic drivers or forcing use of an alternative:

# Blacklist a module
sudo tee /etc/modprobe.d/blacklist-nouveau.conf << 'EOF'
# Blacklist nouveau to use NVIDIA proprietary driver instead
blacklist nouveau
blacklist lbm-nouveau
options nouveau modeset=0
EOF

# For Secure Boot / initramfs-based loading, also add:
sudo tee -a /etc/modprobe.d/blacklist-nouveau.conf << 'EOF'
alias nouveau off
alias lbm-nouveau off
EOF

# Rebuild initramfs to include the blacklist
sudo update-initramfs -u   # Ubuntu
sudo dracut --force        # CentOS/Rocky

# Verify module is not loaded after reboot
lsmod | grep nouveau

Common blacklisting use cases:

# Blacklist PC speaker
sudo tee /etc/modprobe.d/blacklist-pcspkr.conf << 'EOF'
blacklist pcspkr
EOF

# Blacklist USB storage (security hardening)
sudo tee /etc/modprobe.d/blacklist-usb-storage.conf << 'EOF'
blacklist usb-storage
EOF

# Disable IPv6 module
sudo tee /etc/modprobe.d/blacklist-ipv6.conf << 'EOF'
blacklist ipv6
EOF
# Better method: via sysctl
# net.ipv6.conf.all.disable_ipv6 = 1

DKMS for Out-of-Tree Modules

DKMS (Dynamic Kernel Module Support) automatically rebuilds out-of-tree modules when the kernel is updated:

# Install DKMS
sudo apt install dkms build-essential linux-headers-$(uname -r)   # Ubuntu
sudo dnf install dkms kernel-devel                                  # CentOS/Rocky

# List DKMS modules
sudo dkms status

# Add a module to DKMS (example with VirtualBox kernel module)
# Typically done automatically by package installer

# Manual DKMS module setup example
MODULE="v4l2loopback"
VERSION="0.12.7"

# Install the source
sudo apt install v4l2loopback-dkms   # Ubuntu

# Or manually:
# 1. Place source in /usr/src/MODULE-VERSION/
# 2. Create dkms.conf

sudo tee /usr/src/${MODULE}-${VERSION}/dkms.conf << 'EOF'
PACKAGE_NAME="v4l2loopback"
PACKAGE_VERSION="0.12.7"
BUILT_MODULE_LOCATION=./
BUILT_MODULE_NAME[0]="v4l2loopback"
DEST_MODULE_LOCATION[0]="/updates/dkms"
AUTOINSTALL="yes"
EOF

# Add, build, and install via DKMS
sudo dkms add -m $MODULE -v $VERSION
sudo dkms build -m $MODULE -v $VERSION
sudo dkms install -m $MODULE -v $VERSION

# Verify
sudo dkms status
lsmod | grep v4l2loopback

Remove a DKMS module:

sudo dkms remove v4l2loopback/0.12.7 --all

Building a Simple Module

Build a minimal "Hello World" kernel module:

# Install build dependencies
sudo apt install build-essential linux-headers-$(uname -r)   # Ubuntu
sudo dnf install kernel-devel kernel-headers gcc make        # CentOS/Rocky

# Create module source
mkdir ~/hello-module && cd ~/hello-module

cat > hello.c << 'EOF'
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Admin");
MODULE_DESCRIPTION("Hello World Kernel Module");
MODULE_VERSION("1.0");

static int __init hello_init(void) {
    printk(KERN_INFO "hello: module loaded\n");
    return 0;
}

static void __exit hello_exit(void) {
    printk(KERN_INFO "hello: module unloaded\n");
}

module_init(hello_init);
module_exit(hello_exit);
EOF

cat > Makefile << 'EOF'
obj-m += hello.o
KDIR := /lib/modules/$(shell uname -r)/build

all:
	make -C $(KDIR) M=$(PWD) modules

clean:
	make -C $(KDIR) M=$(PWD) clean
EOF

# Build
make

# Load and test
sudo insmod hello.ko
lsmod | grep hello
dmesg | tail -3
# Should show: hello: module loaded

# Unload
sudo rmmod hello
dmesg | tail -3

Troubleshooting

Module fails to load with "not found" error:

# Update module dependency cache
sudo depmod -a

# Check if module exists
find /lib/modules/$(uname -r) -name "*.ko*" | grep modulename

# Check kernel version matches headers
uname -r
ls /lib/modules/

Module loads but device not detected:

# Check dmesg for errors immediately after loading
dmesg | tail -20

# Check if hardware is detected
lspci -k   # For PCI devices - shows which module is assigned
lsusb      # For USB devices

DKMS build fails after kernel update:

# Install headers for new kernel
sudo apt install linux-headers-$(uname -r)   # Ubuntu
sudo dnf install kernel-devel-$(uname -r)    # CentOS/Rocky

# Rebuild DKMS modules
sudo dkms autoinstall

# Or rebuild specific module
sudo dkms build v4l2loopback/0.12.7

Module listed in blacklist but still loads:

# Check if it's being loaded as a dependency
modinfo --field=depends my-preferred-module

# Blacklist must also include alias
grep -r modulename /etc/modprobe.d/

# Rebuild initramfs (blacklist must be in initramfs to take effect early)
sudo update-initramfs -u   # Ubuntu
sudo dracut --force        # CentOS/Rocky

"Required key not available" on module load (Secure Boot):

# Module is unsigned, Secure Boot rejects it
# Option 1: Disable Secure Boot in UEFI firmware settings
# Option 2: Sign the module with a MOK key
openssl req -new -x509 -newkey rsa:2048 -keyout signing_key.pem \
  -out signing_cert.pem -days 365 -subj "/CN=Module Signing/" -nodes
/usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 \
  signing_key.pem signing_cert.pem hello.ko
sudo mokutil --import signing_cert.pem

Conclusion

Linux kernel module management is central to controlling hardware support and kernel features on production servers. Use modprobe with /etc/modprobe.d/ for persistent parameters, /etc/modules-load.d/ for automatic loading, and blacklists to prevent problematic modules from loading. For drivers that must survive kernel updates, DKMS is the right tool—install your vendor's DKMS package and it will automatically rebuild the module every time the kernel is updated.