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=y   # built-in module

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

$ 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)

$ find /lib/modules/$(uname -r) -name ‘*.ko’

/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

$ /sbin/modinfo irda

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.

$ /sbin/modinfo -F license irda

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.

<img alt="" data-lazy- data-lazy-src="https://kirelos.com/wp-content/uploads/2021/02/echo/1-6.jpg" data-lazy- height="494" src="data:image/svg xml,” width=”761″>

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

$ /sbin/modprobe -c | grep ipv6

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

$ /sbin/modprobe –show-depends i915

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.

<img alt="" data-lazy- data-lazy-src="https://kirelos.com/wp-content/uploads/2021/02/echo/2-5.jpg" data-lazy- height="361" src="data:image/svg xml,” width=”930″>

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

# insmod /lib/modules/3.16.0-7-amd64/kernel/net/irda/irda.ko

# 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

# rmmod irda

# 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

About the author

<img alt="Avatar" data-lazy-src="https://secure.gravatar.com/avatar/0e10d1ac4a2a52eba66e955619a4e389?s=112&r=g" height="112" src="data:image/svg xml,” width=”112″>

Frank Hofmann

Frank Hofmann is an IT developer, trainer, and author and prefers to work from Berlin, Geneva and Cape Town. Co-author of the Debian Package Management Book available from dpmb.org.