modules: introduction


Learning objective

Understand why and how to write a simple kernel module


Overview

  1. What is a kernel module?

  2. Why write a kernel module?

  3. Important considerations

  4. How to load and unload

  5. Building up an example


Question

What is the difference between a kernel module and a device driver?


What is a kernel module?

Definition: a kernel module is a chunk of code that can be loaded into the kernel at runtime


What is a kernel module?

Modify the kernel without re-compiling or even rebooting

  1. Written in C, but now can be written in rust

What is a kernel module?

Built as a *.ko file

  1. A "kernel object" in ELF format

ELF sidenote

ELF: Executable and linkable format

  1. Unix standard for executable binaries and more

demo

file on a module object file


What a kernel module is not:

  1. executable by itself, nor is it synchronous

  2. safe, since all code runs directly in the kernel

  3. a driver, rather it is a mechanism by which to implement a driver


Why write a kernel module?

  1. Keep the main kernel small

  2. Quicker development process

  3. Distribution flexibility


Question

What could we use modules for?


Common kernel module use-cases

  1. Device drivers

  2. Filesystem support e.g. ext4, xfs, and nfs

  3. Network protocol support such as ipv6

  4. Cryptographic protocols like sha256 and aes

  5. Virtualization module, e.g. KVM


demo

lsmod

demo

ls /lib/modules/$(uname -r)

demo

/proc/modules
  1. module_name: The name of the loaded module

  2. size: Memory size used by the module (in bytes)

  3. used_count: The number of processes using this module

  4. dependencies: List of other modules that this module depends on (comma-separated)

  5. state: Module state (Live, Loading, or Unloading)

  6. offset: The kernel memory offset where the module is loaded


Do we need modules?


Modules are an optional feature

Toggled in the compilation configuration


demo

look at .config/menuconfig tri-state options

  1. In kernel repo: make help | grep all.*config

Multiple entry points

  1. No main(), but init() runs on module load

  2. Define exit() to be able to unload

  3. Other entry points depend on module purpose

    1. e.g. probe(), members of struct file_operations

Versioning

  1. Modules must be compiled for specific kernel version

  2. May access kernel symbol table

  3. May export it's own symbols


demo

EXPORT_SYMBOL


In-tree vs out-of-tree

The tree in question: kernel repository


In-tree

Build a module during kernel build process

  1. New modules require changes to kernel build system

demo

Take a look at how new modules can be added to kernel build system


Out-of-tree

Build modules as standalone units

  1. Loading an out-of-tree (oot) module can mark the kernel as "tainted"

  2. To install dependencies to build modules for current version:

    1. sudo dnf install kernel-devel-$(uname -r)

Loading and unloading

3 main utilities:

  1. insmod

  2. rmmod

  3. modprobe


What is the difference?

  1. insmod takes a path to a *.ko file

  2. modprobe take a module name in the /lib/modules/$(uname -r) subtree

  3. rmmod and modprobe -r takes the name of a loaded module


Underlying system calls

  1. init_module(2) loads a struct module into the kernel

  2. finit_module(2) does the same thing with a file descriptor

  3. delete_module(2) removes a module given it's name


demo

ikconfig in the minimal distro: in-tree

  1. See: kernel/configs.c

    1. plenty of stuff we will return to
  2. Built as the module in the minimal linux demo rootfs

  3. Show inserting/removing in different ways

  4. Show /proc/module address in /proc/kallsyms

  5. Show bits in /sys/module


demo

The most minimal module possible

  1. MODULE_LICENSE("GPL") is the only required meta information

demo

minimal but removable module


demo

print on enter and exit: A "Hello world" module


demo

Take a look at include/linux/module.h


Summary

Why and how to write a simple kernel module


Summary

A Linux kernel module is an ELF object that can be loaded into a running kernel


Summary

Modularization can reduce the kernel binary size and attack surface


Summary

Use kernel modules to implement device drivers, filesystems, network protocols, and more

  1. Can be built within or seperately from the rest of the kernel

Summary

Multiple entry points, including init() which is run at load time


Summary

Build using makefile provided by the kernel repository


Summary

Load and unload using modprobe, insmod, and rmmod

  1. Inspect loaded modules with lsmod or the /proc/modules file

End


msg = (silence)
whoami = None
singularity v0.6-56-g8e52bc8 https://github.com/underground-software/singularity