Is it difficult to write a kernel module?
A minimal kernel module for FreeBSD
Introduction
Writing a kernel module looks like something that can be achieved by people with large experience. While there is some truth on that, it is actually not that difficult to move functionality into kernel modules.
In this post I will compile from scratch the skeleton of a kernel module named morse. The module will later be enhanced to create a new device file that takes English as input and outputs the equivalent translation in morse. It has obviously almost no other value than being an educational example on how to manage kernel modules. As discussed I will first just create the skeleton of the module.
While writing kernel modules is not a common needs, they have a place in proprietary systems, as they can build easy to consume services that can do things such as systems bypassing kernel stacks for performance.
Resources to learn about FreeBSD kernel
I am far from being an expert in the FreeBSD kernel, as I am just started to play around it. I have some toy side ideas that I want to explore bypassing kernel stacks and hence I decided to have a look on which resources are available to learn how to do that.
It happens that it is not that easy to find documentation or resources to begin with, and most of the recommendations you are going to find are about reading the source code itself.
The Design and Implementation of the FreeBSD Operating System is always recommended when somebody asks about learning FreeBSD kernel. The book written by Marshall McKusick, George Neville-Neil and Robert Watson is a very good introduction on how FreeBSD is organised. I would not say that the book is self-contained or the best hands-on resource -because it is not- but it is definitively a resource if you are interested in these topics. McKusick also sells some companion videos on the matter in his web site, although they are a bit expensive for the hobbyist IMHO. I suspect the videos are more intended for professional users, as FreeBSD is often used as reference kernel for well funded industry solutions.
More resources can be found in the FreeBSD official user forums and they point to Designing BSD Rootkits: An Introduction to Kernel Hacking by Joseph Kong (I have not read it, therefore I have no opinion on it) and the FreeBSD Developer’s and Architecture Handbooks.
Ultimately I suspect that a big deal of experimentation and reading of existing kernel modules is actually required to do any serious work.
In my opinion the topic is not that well covered by the community, likely because it is not an easy one and nobody wants to babysit newcomers.
Your first loadable kernel module
Kernels do no longer require you recompiling the entire kernel to add a module. A new module can be compiled and loaded and unloaded dynamically. In my example I am working under FreeBSD. A sample skeleton file can be found in FreeBSD handbook and it would be as follows:
With its corresponding makefile:
In order to compile the module you just have to to download the source code (in this example I am using FreeBSD 13.1 so I will download the source code for that specific branch) that must be under /usr/src and type make.
# cd /usr/src
# git clone -b releng/13.1 --depth 1 https://git.freebsd.org/src.git$ cd /home/user/
$ git clone https://github.com/marioemmanuel/freebsd_kernel_samplemodule_1
$ make
The module can be later loaded with kld utils as any other kernel module:
# kldload -v ./morse.ko
Morse KLD loaded.
Loaded ./morse.ko, id=13
# kldstat
Id Refs Address Size Name
1 47 0xffffffff80200000 1f30590 kernel
2 1 0xffffffff82320000 158438 i915kms.ko
3 1 0xffffffff82479000 7f020 drm.ko
4 2 0xffffffff824f9000 cbc8 linuxkpi_gplv2.ko
5 1 0xffffffff82506000 3250 ichsmb.ko
6 1 0xffffffff8250a000 2180 smbus.ko
7 1 0xffffffff8250d000 2110 pchtherm.ko
8 1 0xffffffff82510000 2340 uhid.ko
9 1 0xffffffff82513000 4350 ums.ko
10 1 0xffffffff82518000 3380 usbhid.ko
11 1 0xffffffff8251c000 31f8 hidbus.ko
12 1 0xffffffff82520000 2a08 mac_ntpd.ko
13 1 0xffffffff82523000 2088 morse.ko
# kldunload morse
Morse KLD unloaded.
Congratulations. You have compiled and loaded your first FreeBSD module, that was not that difficult, right? In another post I will attach the functionality to get our device level morse encoder.