Understanding the Linux kernel
The Linux kernel is the core of the Linux operating system. It contains the main components to address the hardware and allows both communication and interaction between the user and the hardware. The Linux kernel is not a monolithic system but quite flexible, and the kernel is extended by so-called kernel modules.
What is a kernel module?
In general, a kernel module is a “piece of code that can be loaded and unloaded into the kernel upon demand. They extend the functionality of the kernel without the need to reboot the system” [1]. This leads to very great flexibility during operation.
Furthermore, “a kernel module can be configured as built-in or loadable. To dynamically load or remove a module, it has to be configured as a loadable module in the kernel configuration” [1]. This is done in the kernel source file /usr/src/linux/.config [2]. Built-in modules are marked with “y” and loadable modules with “m”. As an example, listing 1 demonstrates this for the SCSI module:
Listing 1: SCSI module usage declaration
CONFIG_SCSI=m # loadable module
# CONFIG_SCSI # variable is not set
We do not recommend editing the configuration file directly, but to use either the command “make config”, “make menuconfig”, or “make xconfig” to define the usage of the corresponding module in the Linux kernel.
Module commands
The Linux system comes with a number of different commands to handle kernel modules. This includes listing the modules currently loaded into the Linux kernel, displaying module information, as well as loading and unloading kernel modules. Below we will explain these commands in more detail.
For the current Linux kernels, the following commands are provided by the kmod package [3]. All the commands are symbolic links to kmod.
The list currently loaded modules with lsmod
We start with the lsmod command. lsmod abbreviates “list modules” and displays all modules currently loaded into the Linux kernel by nicely formatting the contents of the file /proc/modules. Listing 2 shows its output that consists of three columns: module name, the size used in memory, and other kernel modules that use this specific one.
Listing 2: Using lsmod
Module Size Used by
ctr 12927 2
ccm 17534 2
snd_hrtimer 12604 1
snd_seq 57112 1
snd_seq_device 13132 1 snd_seq
...
$
Find available modules for your current kernel
There might be kernel modules available that you are not aware of yet. They are stored in the directory /lib/modules. With the help of find, combined with the uname command, you can print a list of these modules. “uname -r” just prints the version of the currently running Linux kernel. Listing 3 demonstrates this for an older 3.16.0-7 Linux
kernel, and shows modules for IPv6 and IRDA.
Listing 3: Displaying available modules (selection)
/lib/modules/3.16.0-7-amd64/kernel/net/ipv6/ip6_vti.ko
/lib/modules/3.16.0-7-amd64/kernel/net/ipv6/xfrm6_tunnel.ko
/lib/modules/3.16.0-7-amd64/kernel/net/ipv6/ip6_tunnel.ko
/lib/modules/3.16.0-7-amd64/kernel/net/ipv6/ip6_gre.ko
/lib/modules/3.16.0-7-amd64/kernel/net/irda/irnet/irnet.ko
/lib/modules/3.16.0-7-amd64/kernel/net/irda/irlan/irlan.ko
/lib/modules/3.16.0-7-amd64/kernel/net/irda/irda.ko
/lib/modules/3.16.0-7-amd64/kernel/net/irda/ircomm/ircomm.ko
/lib/modules/3.16.0-7-amd64/kernel/net/irda/ircomm/ircomm-tty.ko
...
$
Display module information using modinfo
The command modinfo tells you more about the requested kernel module (“module information”). As a parameter, modinfo requires either the full module path or simply the module name. Listing 4 demonstrates this for the IrDA kernel module dealing with the Infrared Direct Access protocol stack.
Listing 4: Display module information
filename: /lib/modules/3.16.0-7-amd64/kernel/net/irda/irda.ko
alias: net-pf-23
license: GPL
description: The Linux IrDA Protocol Stack
author: Dag Brattli <dagb@cs.uit.no> & Jean Tourrilhes <jt@hpl.hp.com>
depends: crc-ccitt
vermagic: 3.16.0-7-amd64 SMP mod_unload modversions
$
The output contains different information fields such as the full path for the kernel module, its alias name, software license, module description, authors, as well as kernel internals. The field “depends” shows which other kernel modules it depends on.
The information fields differ from module to module. In order to limit the output to a specific information field, modinfo accepts the parameter “-F” (short for “–field”) followed by the field name. In Listing 5, the output is limited to the license information made available using the license field.
Listing 5: Display a specific field only.
GPL
$
In newer Linux kernels, a useful security feature is available. This covers cryptographically signed kernel modules. As explained on the Linux kernel project website [4], “this allows increased kernel security by disallowing the loading of unsigned modules or modules
signed with an invalid key. Module signing increases security by making it harder to load a malicious module into the kernel. The module signature checking is done by the kernel so that it is not necessary to have “trusted userspace bits.” The figure below shows this for the
parport_pc module.
Show module configuration using modprobe
Every kernel module comes with a specific configuration. The command modprobe followed by the option “-c” (short for “–showconfig”) lists the module configuration. In combination with grep, this output is limited to a specific symbol. Listing 6 demonstrates this for IPv6 options.
Listing 6: Show module configuration
alias net_pf_10_proto_0_type_6 dccp_ipv6
alias net_pf_10_proto_33_type_6 dccp_ipv6
alias nf_conntrack_10 nf_conntrack_ipv6
alias nf_nat_10 nf_nat_ipv6
alias nft_afinfo_10 nf_tables_ipv6
alias nft_chain_10_nat nft_chain_nat_ipv6
alias nft_chain_10_route nft_chain_route_ipv6
alias nft_expr_10_reject nft_reject_ipv6
alias symbol:nf_defrag_ipv6_enable nf_defrag_ipv6
alias symbol:nf_nat_icmpv6_reply_translation nf_nat_ipv6
alias symbol:nft_af_ipv6 nf_tables_ipv6
alias symbol:nft_reject_ipv6_eval nft_reject_ipv6
$
Show module dependencies
The Linux kernel is designed to be modular, and functionality is distributed over a number of modules. This leads to several module dependencies that can be displayed using modprobe again. Listing 7 uses the option “–show-depends” in order to list the dependencies for the i915 module.
Listing 7: Show module dependencies
insmod /lib/modules/3.16.0-7-amd64/kernel/drivers/i2c/i2c-core.ko
insmod /lib/modules/3.16.0-7-amd64/kernel/drivers/i2c/algos/i2c-algo-bit.ko
insmod /lib/modules/3.16.0-7-amd64/kernel/drivers/thermal/thermal_sys.ko
insmod /lib/modules/3.16.0-7-amd64/kernel/drivers/gpu/drm/drm.ko
insmod /lib/modules/3.16.0-7-amd64/kernel/drivers/gpu/drm/drm_kms_helper.ko
insmod /lib/modules/3.16.0-7-amd64/kernel/drivers/acpi/video.ko
insmod /lib/modules/3.16.0-7-amd64/kernel/drivers/acpi/button.ko
insmod /lib/modules/3.16.0-7-amd64/kernel/drivers/gpu/drm/i915/i915.ko
$
In order to display the dependencies as a tree similar to the “tree” or “lsblk” command, the modtree project [5] can help (see figure below for the i915 module tree). Although it is freely available on GitHub, it requires some adaptations to comply with the rules for free software and to become part of a Linux distribution as a package.
Loading modules
Loading a module to a running kernel can be done by two commands — insmod (“insert module”) and modprobe. Be aware that there is a slight but important difference between these two: insmod does not resolve module dependencies, but modprobe is cleverer and does that.
Listing 8 shows how to insert the IrDA kernel module. Please note that insmode works with the full module path, whereas modprobe is happy with the name of the module and looks it up itself in the module tree for the current Linux kernel.
Listing 8: Inserting a kernel module
...
# modprobe irda
Unloading modules
The last step deals with unloading modules from a running kernel. Again, there are two commands available for this task — modprobe and rmmod (“remove module”). Both commands expect the module name as a parameter. Listing 9 shows this for removing the IrDA module from the running Linux kernel.
Listing 9: Removing a kernel module
...
# modprobe -r irda
...
Conclusion
Handling Linux kernel modules is not big magic. Just a few commands to learn, and you are the master of the kitchen.
Thank you
The author would like to thank Axel Beckert (ETH Zürich) and Saif du Plessis (Hothead Studio Cape Town) for their help while preparing the article.
Links and References
- [1] Kernel module, Arch Linux wiki, https://wiki.archlinux.org/index.php/Kernel_module
- [2] Kernel Configuration, https://tldp.org/HOWTO/SCSI-2.4-HOWTO/kconfig.html
- [3] kmod, https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git
- [4] Kernel module signing facility, https://www.kernel.org/doc/html/v4.15/admin-guide/module-signing.html
- [5] modtree, https://github.com/falconindy/modtree