Linux kernel modules

Table of contents

1. What are kernel modules

2. Getting information about modules

3. Automatic module loading using systemd

4. Manual processing of modules (enable and disable modules and drivers)

4.1 How to use the driver without installing it

5. Modules blacklisting

5.1 How to block all network interfaces on a computer

5.2 How to reliably turn off the webcam

6. Setting module options

7. Aliases

8. Kernel modules troubleshooting

8.1 Modules do not load

8.2 modprobe: ERROR: could not insert '…': Unknown symbol in module, or unknown parameter (see dmesg)

8.3 modprobe: FATAL: Module … not found in directory /lib/modules/…


What are kernel modules

Kernel modules are pieces of code that can be loaded and unloaded into the kernel on demand. They extend the functionality of the kernel without having to reboot the system. The module can be configured as built-in to the kernel or loaded while the operating system is running.

Examples of kernel modules are drivers for various devices.

In this article you will learn:

  • how to find out which kernel modules are running (loaded)
  • how to find out which driver is used for the specified device and how to get information about this driver
  • how to reliably disable devices (for example, network cards, webcams and others) so that they cannot be turned on and used
  • how to try a new driver without installing it in the system

Getting information about modules

Modules are stored in the /usr/lib/modules/KERNEL_RELEASE directory. The current folder with modules can be found with the command:

echo /lib/modules/`uname -r`

Output Example:

/lib/modules/5.6.14-arch1-1

Module names often contain underscores (_) or hyphens (-); these symbols are interchangeable in the modprobe commands and in the configuration files in the /etc/modprobe.d/ directory.

The lsmod command shows the drivers and other modules that are currently loaded. To see which modules are currently loaded, type:

lsmod

or command

kmod list

In fact, this is one and the same. Information is read from /proc/modules and these commands only display it in a more understandable way.

To display information about the module, use the modinfo command:

modinfo MODULE_NAME

If you get an error:

bash: modinfo: command not found

Then run modinfo with sudo.

For example, to find out information about the iwlwifi module:

modinfo iwlwifi

How to understand modinfo output

modinfo output is extensive and contains a lot of information.

The “filename” line shows the full path to the module file.

The line “author” contains information about the creator of the module, for example, “Copyright (c) 2003-2015 Intel Corporation <linuxwifi@intel.com>”

In the “description” line is a description of the module, for example, “Intel (R) Wireless WiFi driver for Linux”.

Let’s consider how to interpret strings

  • firmware
  • alias
  • intree
  • vermagic

on the example of the i915 module

modinfo i915

Output snippet:

filename:       /lib/modules/4.2.0-1-amd64/kernel/drivers/gpu/drm/i915/i915.ko
license:        GPL and additional rights
description:    Intel Graphics
author:         Intel Corporation
[...]
firmware:       i915/skl_dmc_ver1.bin
alias:          pci:v00008086d00005A84sv*sd*bc03sc*i*
[...]
depends:        drm_kms_helper,drm,video,button,i2c-algo-bit
intree:         Y
vermagic:       4.2.0-1-amd64 SMP mod_unload modversions
parm:           modeset:Use kernel modesetting [KMS] (0=DRM_I915_KMS from .config, 1=on, -1=force vga console preference [default]) (int)
[...]

firmware:

firmware:       i915/skl_dmc_ver1.bin

Many devices require two things to work properly: a driver and firmware. The driver requests firmware from the file system in /lib/firmware. This is a special file necessary for hardware, it is not a binary file. Then the diver uploads the firmware to the device. The firmware performs programming of the equipment inside the device.

alias:

alias:          pci:v00008086d00005A84sv*sd*bc03sc*i*

This entry can be divided into parts by colons (:)

  • pci: device type, pci or usb
  • v00008086: v denotes the identifier of the supplier, it identifies the vendor of the equipment. This list is maintained by the PCI Special Interest Group. The number 0x8086 means “Intel Corporation”.
  • d00005A84: d is the device identifier selected by the vendor. This identifier is usually connected to the vendor identifier to create a unique 32-bit identifier for the hardware device. There is no official list.
  • sv*, sd*: subsystem provider version and subsystem device version for further device identification (* indicates that it will correspond to anything)
  • bc03: base class. It determines what kind of device it is; IDE interface, Ethernet controller, USB controller, … bc03 means display controller. You can notice them from the output of lspci because lspci maps the number and class of the device.
  • sc*: subclass of the base class.
  • i*: interface

intree:

intree:         Y

All kernel modules begin their development as outside the tree. Once a module is accepted for inclusion, it becomes a module inside the tree. Modules without this flag (set to N) can ruin the kernel.

vermagic:

vermagic:       4.2.0-1-amd64 SMP mod_unload modversions

When the module loads, the vermagic string is checked for compliance with the current kernel version. If they do not match, you will receive an error and the kernel will refuse to load the module. You can overcome this by using the --force flag in modprobe. Naturally, these checks exist for your protection, so using this option is dangerous.

To display a list of options installed for a loaded module:

systool -v -m MODULE_NAME

If you get an error:

bash: systool: command not found

Then install the sysfsutils package.

Example output for the iwlwifi module:

systool -v -m iwlwifi

To display the full configuration of all modules:

modprobe -c | less

To display the configuration of a specific module:

modprobe -c | grep MODULE_NAME

To list the dependencies of a module (or an alias), including the module itself:

modprobe --show-depends MODULE_NAME

Automatic module loading using systemd

Today, loading all the necessary modules is performed by udev automatically, so there is no need to put the modules in any configuration file. However, in some cases, you may need to download an additional module during the boot process of the computer or add another module to the blacklist for the computer to work properly.

Kernel modules can be explicitly listed in the files in /etc/modules-load.d/ for systemd to load them when the computer is turned on. Each configuration file has a name in the style of /etc/modules-load.d/ <program>.conf. Configuration files simply contain a list of kernel module names for loading, separated by newline characters. Empty lines and lines whose first non-whitespace character is # (hash) or ; (semicolon) are ignored.

Sample file /etc/modules-load.d/virtio-net.conf

# Load virtio_net.ko when you turn on the computer
virtio_net

In addition to the specified directory, configuration files from /run/modules-load.d/*.conf and /usr/lib/modules-load.d/*.conf are also read.

Note that it is usually best to rely on automatic loading of modules using PCI identifiers, USB identifiers, DMI identifiers, or similar triggers encoded in the kernel modules themselves, instead of a static configuration like this. In fact, most modern kernel modules are already prepared for automatic loading.

Manual processing of modules (enable and disable modules and drivers)

Kernel modules are handled by the tools provided by the kmod package. You can use these tools manually.

Note. If you have updated the kernel but have not yet restarted the computer, modprobe will fail with no error message and exit with code 1, since the /usr/lib/modules/$(uname -r)/ path no longer exists.

To load a module, use a command of the form:

sudo modprobe MODULE_NAME

To load a module by file name (that is, one that is not installed in /usr/lib/modules/$(uname -r)/):

sudo insmod FILE_NAME [ARGUMENTS]

To unload (turn off) the module:

sudo modprobe -r MODULE_NAME

Or an alternative command:

sudo rmmod MODULE_NAME

How to use the driver without installing it

Let's look at a real-life example when starting a driver from a file can come in handy.

Let’s consider the driver repository for the RTL8812AU/21AU and RTL8814AU chipsets as an example.

These drivers are designed to operate such modern Wi-Fi dongles with support for Wi-Fi AC standard as:

These drivers support monitor mode and wireless injection, that is, they are suitable for wireless security audit of Wi-Fi networks on 2.4 and 5 GHz, including those with support for Wi-Fi standard AC.

In principle, Kali Linux repositories already have this driver:

apt show realtek-rtl88xxau-dkms

But its version is 5.6.4. But version 5.7.0 is already available. Suppose we want to try version 5.7.0 without installing it on a system.

So, delete the version from the repository (if it was installed)

sudo apt remove realtek-rtl88xxau-dkms

Check that the module is not loaded:

sudo lsmod | grep 88XXau

And when I try to download it, an error occurs:

sudo modprobe 88XXau

module not found:

modprobe: FATAL: Module 88XXau not found in directory /lib/modules/5.6.0-kali1-amd64

Or such an error:

modprobe: ERROR: could not insert '88XXau': Unknown symbol in module, or unknown parameter (see dmesg)

That is, unknown symbol in module. The essence is the same – the module was not found, but previously existed, so references to the dependency lists remained from it.

Install the dependencies necessary to compile this driver:

sudo apt install build-essential bc libelf-dev

We clone the repository – pay attention to the use of the -b option with which the branch of interest is indicated (in this case, the name of the branch matches the version of the driver):

git clone https://github.com/aircrack-ng/rtl8812au -b v5.7.0

We compile, but do not do the installation, since we do not want to install this module:

cd rtl8812au
make

We have two ways to load (enable) a module – using insmod or using the modprobe command. The insmod command is more convenient, because you can specify a compiled driver file, and the modprobe command handles dependencies better, so let's consider both options.

Load a module without installing (using insmod)

To include a module from a file, use a command of the form:

sudo insmod FILE_NAME [ARGUMENTS]

The module files have the .ko extension, in our case the file name is 88XXau.ko, so the command is as follows:

sudo insmod ./88XXau.ko

Check if the module has been loaded:

sudo lsmod | grep 88XXau

Output:

88XXau               3067904  0
cfg80211              864256  1 88XXau
usbcore               315392  6 ohci_hcd,ehci_pci,usbhid,ehci_hcd,ohci_pci,88XXau

The first line shows that the 88XXau module is loaded, and the next lines show the modules that 88XXau uses (that is, which are dependencies for it).

Load a module without installing (using modprobe)

The second option is a bit more complicated to configure, but you do not need to specify the full path to the driver file to load the module.

Unload the module if it was loaded earlier:

sudo rmmod 88XXau

Now we will make the system think that the module is installed, although in reality it is not. To do this, we will create a symbolic link from the .ko file to the /lib/modules/`uname -r` folder:

sudo ln -s /PATH/TO/MODULE.ko /lib/modules/`uname -r`

In our case, to do this, run the following command:

sudo ln -s `pwd`/88XXau.ko /lib/modules/`uname -r`

Update the list of dependencies of all modules (by the way, the -a switch in the following command can be skipped, because it is assumed by default):

sudo depmod -a

Now you can use the regular modprobe command to load the module:

sudo modprobe 88XXau

Check the module version:

sudo modinfo 88XXau

Pay attention to the lines:

filename:       /lib/modules/5.6.0-kali1-amd64/88XXau.ko
version:        v5.7.0_34085.20200313

Version v5.7.0 is used – this is exactly what we achieved.

The described methods for starting modules are suitable for a one-time or occasional driver launch. For permanent use, it is recommended to perform a normal installation a module, in which case it will support DKMS.

DKMS

Drivers can be installed using DKMS. This is a system that automatically recompiles and installs kernel modules when installing or updating a new kernel. To use DKMS, install the dkms package.

Using DKMS, drivers from official repositories are installed. Also, using DKMS, you can install drivers from other repositories (for example, rtl8812au, which was taken as an example just above, it supports) – to do this, follow the official installation instructions from the developers, and the method for starting the driver described above is designed to testing.

Modules blacklisting

Blacklisting, in the context of kernel modules, is a mechanism that prevents the loading of a kernel module. This can be useful if, for example, related equipment is not required or if loading this module causes problems: for example, there may be two kernel modules that are trying to control the same hardware component, and loading them together will lead to a conflict.

Using Files in /etc/modprobe.d/

Create a .conf file inside /etc/modprobe.d/ and add a line for each module that you want to add to the blacklist using the blacklist keyword. For example, if you want to prevent the pcspkr module from loading, create the file /etc/modprobe.d/nobeep.conf and add the line to it:

blacklist pcspkr

Some modules are loaded as part of initramfs. That is, modules can be modules can be classified as:

  • loaded from .ko files
  • loaded as part of initramfs

To prohibit the loading of modules of the first type (loaded from .ko files), it is enough to record this module in the /etc/modprobe.d/*.conf file with the blacklist directive.

For modules of the second type (loaded as part of initramfs), in addition to creating the configuration file, it is also necessary to recreate the kernel.

Note. The blacklist command will blacklist the module so that it does not load automatically. But at the same time, the module can be loaded if another module, not included in the black list, depends on it, and you can still load the module manually. However, there is a workaround for this behavior; the install command tells modprobe to run a user command instead of inserting the module into the kernel as usual, so you can force the module to never load using the construction discussed below. Suppose you created the file /etc/modprobe.d/blacklist.conf to block the loading of the module MODULE_NAME. To do this reliably, add to this file:

blacklist MODULE_NAME
install MODULE_NAME /bin/true

This will reliably block the loading of the specified module, as well as any other, depending on it.

How to recreate the kernel to block modules

If you block modules that are loaded from initramfs, then after adding them to the /etc/modprobe.d/*.conf file, you need to recreate the kernel.

On Debian, Kali Linux, Linux Mint, Ubuntu and their derivatives this is done like this:

sudo update-initramfs -u
sudo reboot

In Arch Linux, BlackArch, and their derivatives, this is done like this:

sudo mkinitcpio -g /boot/initramfs-linux.img -k /boot/vmlinuz-linux

Arch Linux command

mkinitcpio -M

prints all automatically detected modules: to prevent some of these initramfs from loading, blacklist them in the .conf file in /etc/modprobe.d and it will be added by the modconf hook during image generation. Launch

mkinitcpio -v

to list all the modules involved by various hooks (for example, filesystems hook, block hook, etc.).

Blacklisting modules at the start of Linux boot (disabling modules on the kernel command line)

This can be very useful if a faulty module makes it impossible to boot your system. You can blacklist modules in the bootloader menu. Just add

module_blacklist=MODULE-NAME1,MODULE-NAME2,MODULE-NAME3

in a line with kernel boot parameters.

Examples of editing kernel boot parameters for popular distributions can be found in the article “How to reset a forgotten login password in Linux”. Also see the article “How to change Linux boot parameters in UEFI”.

Note. If you blacklist more than one module, keep in mind that they are separated only by commas. Spaces or anything else can break the syntax.

Consider practical examples where a user may need to block the loading of kernel modules.

How to block all network interfaces on a computer

Suppose it is necessary that any network activity, that is, both wired and wireless networks, is blocked on the computer. There is an rfkill command, but it is designed to block only wireless networks. Therefore, we find another way.

The algorithm of actions is as follows:

  1. We will determine which drivers are used by network devices.
  2. Blacklist these drivers

To find out which drivers are used in Linux for network cards, run the command:

sudo lshw -C network

The “configuration:” lines contain information about the drivers. For a wireless card it is “driver=iwlwifi”, and for a wired network interface it is “driver=r8169”.

Create the file /etc/modprobe.d/block-network.conf and add to it:

blacklist iwlwifi
install iwlwifi /bin/true

blacklist r8169
install r8169 /bin/true

This is how the network setup looks in normal condition, the wired and wireless adapters are visible:

After reboot, it will not be possible to turn on the network, because the computer will not be able to use network interfaces without drivers:

When trying to load modules manually, for example:

sudo modprobe iwlwifi

These modules will not load thanks to the install command.

You cannot turn on any network until you delete the /etc/modprobe.d/block-network.conf file and reboot. However, if other network adapters are plugged, they will be used. This method will reliably protect against accidental use of the network, provided that you control the plugging of new physical devices to the computer.

How to reliably turn off the webcam

On some new laptop models, you can close the webcam with a shutter – in case you are afraid that a hacker might hack your computer and use the webcam of your laptop to look at you.

Now we will learn how to disable the webcam driver so that it cannot be used.

Even if you have a laptop, most likely the web camera is connected inside the case to a USB hub, that is, it is a USB device. To list USB devices in the system, use the command:

lsusb

Pay attention to IMC Networks USB2.0 HD UVC WebCam in the list above – this is the laptop’s webcam.

To determine the drivers that are needed for any USB or PCI device to work on your system, use the following commands:

# To list only USB devices and their drivers
usb-devices

# To list only PCI devices and their drivers
lspci -k

# To list both USB and PCI devices and their drivers
sudo lshw

We use the command:

usb-devices

We see that the uvcvideo driver is used for the USB2.0 HD UVC WebCam device.

We create the file /etc/modprobe.d/block-webcam.conf and block the launch of the uvcvideo kernel module in it:

blacklist uvcvideo
install uvcvideo /bin/true

After rebooting, the system will not be able to use the webcam until the block-webcam.conf file is deleted and the system is rebooted.

Setting module options

To pass an option to the kernel module, you can pass them manually using modprobe or make sure that certain parameters are always applied using the modprobe configuration file or using the kernel command line.

Manually at boot time using modprobe

The main way to pass parameters to a module is to use the modprobe command. Parameters are specified on the command line using simple key=value assignments:

modprobe MODULE-NAME PARAMETER-NAME=PARAMETER-VALUE

Using files in /etc/modprobe.d/

Files in the /etc/modprobe.d/ directory can be used to transfer module settings to udev, which will use modprobe to control module loading during system boot. The configuration files in this directory can have any name if they end with the .conf extension, for example /etc/modprobe.d/myfilename.conf. Syntax:

options MODULE-NAME PARAMETER-NAME=VALUE-PARAMETER

For example, the contents of the file /etc/modprobe.d/thinkfan.conf:

# on ThinkPads, this setting allows the thinkfan daemon to control fan speed
options thinkpad_acpi fan_control=1

Adding module options during system boot (using the kernel command line)

If the module is built into the kernel, you can also pass options to the module using the kernel command line. For all common bootloaders, the correct syntax is:

MODULE-NAME.PARAMETER-NAME=PARAMETER-VALUE

For instance:

thinkpad_acpi.fan_control=1

Aliases

Aliases are alternative names for the module. For instance:

alias MY-MOD VERY-LONG-MODULE-NAME

means you can use

modprobe MY-MOD

instead

modprobe VERY-LONG-MODULE-NAME

You can also use shell-style wildcards, so

alias my-mod* really_long_modulename

means that

modprobe my-mod-something

has the same effect.

To create an alias in the configuration file /etc/modprobe.d/myalias.conf:

alias MY-MOD VERY-LONG-MODULE-NAME

Some modules have aliases that are used to automatically load them when the application needs them. Disabling these aliases can prevent automatic loading, but it still allows you to load modules manually.

Sample file /etc/modprobe.d/modprobe.conf

# Prevent Bluetooth auto download
alias net-pf-31 off

Kernel modules troubleshooting

Modules do not load

If a certain module does not load, and in the boot log

journalctl -b

it says that the module is in the blacklist, but there is no corresponding entry in the /etc/modprobe.d/ directory, check another modprobe folder for the presence of the blacklist entry: /usr/lib/modprobe.d/.

A module will not be loaded if the "vermagic" string contained within the kernel module does not match the value of the currently running kernel. If it is known that the module is compatible with the current running kernel the "vermagic" check can be ignored with modprobe --force-vermagic.

Warning. Ignoring version checks for a kernel module can lead to a kernel crash or unpredictable system behavior due to incompatibility. Use --force-vermagic with extreme caution.

modprobe: ERROR: could not insert '…': Unknown symbol in module, or unknown parameter (see dmesg)

Example:

modprobe: ERROR: could not insert '88XXau': Unknown symbol in module, or unknown parameter (see dmesg)

The error is caused by the fact that the module was previously present in the system and an entry in the list of dependencies was left about it, but at the time of the error the module was missing (removed).

To update the list of dependencies, run the command:

sudo depmod -a

modprobe: FATAL: Module … not found in directory /lib/modules/…

Example:

modprobe: FATAL: Module 88XXau not found in directory /lib/modules/5.6.0-kali1-amd64

Means that the module you are trying to run does not exist.

Possible reasons:

  • typo in the module name
  • the package containing the specified module is not installed or removed

If previously the module (driver) was launched, but then the indicated error appeared, then it may be due to the fact that the kernel was updated, and the module for the new version of the kernel was not compiled.

Recommended for you:

One Comment to Linux kernel modules

  1. didier says:

    Very interresting article as usual 

     

    thx

Leave a Reply to didier Cancel reply

Your email address will not be published.