As previously mentioned in an article where we compiled our kernel, different kernel parameters can be compiled into the kernel itself or as a module. Compiling as a module gives us greater flexibility as we can load the module with different parameters, but on the other hand, it exposes us to dreaded rootkits.
This time we will learn to compile a very simple module whose only mission is to print a message in the system logs. It may not be much, but it will suffice as an introduction to module programming.
The modules are located in a specific directory, /lib/modules/version/. The main commands used for their management are as follows:
- depmod -a: Generates the /lib/modules/version/modules.dep file where the module dependencies are indicated.
- insmod: Loads a module without checking dependencies. If there are dependencies, they must be loaded in the correct order manually, and the exact location of the module must be specified.
- modprobe: Loads the module taking into account the dependencies. It searches the default directory to load the modules.
- rmmod: Unloads the module.
Every module consists of at least two parts:
- init_module –> main() It is executed when the module is loaded: insmod, modprobe.
- cleanup_module –> It is executed when the module is unloaded: rmmod.
In our example, we will simply print a message through syslog when loading the module and another one when unloading it:
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
int init_module(void)
{
printk(KERN_INFO "Hello world 1.
");
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.
");
}
We create a makefile to be able to compile it:
obj-m += my_module.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
NOTE: The makefile’s tabulations are very important. If edited with Vi, you can see how it changes color when tabulated.
We compile:
make -C /lib/modules/3.16.5-gentoo-Kr0m-ceph-xfs-xen/build M=/home/XXXX modules
make[1]: Entering directory '/usr/src/linux-3.16.5-gentoo'
CC [M] /home/XXXX/my_module.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/XXXX/my_module.mod.o
LD [M] /home/XXXX/my_module.ko
make[1]: Leaving directory '/usr/src/linux-3.16.5-gentoo'
We can now load the module, but first we will leave a tail in the system logs to verify that it has been successfully loaded:
In another terminal, we load the module:
my_module 812 0
In the console with the tail, we will see:
Nov 18 21:46:30 localhost kernel: [981248.867904] Hello world 1.
If we unload it:
In the console with the tail, we will see:
Nov 18 21:49:08 localhost kernel: [981407.803926] Goodbye world 1.
This can be a first step towards programming our own rootkit ;)