This page looks best with JavaScript enabled

Programming modules for the Linux kernel

 ·  🎃 kr0m

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:

vi my_module.c

#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:

vi Makefile

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 all
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:

tail -f /var/log/messages

In another terminal, we load the module:

insmod my_module.ko

lsmod|grep my_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:

rmmod my_module

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

If you liked the article, you can treat me to a RedBull here