Paul Kiddie

Creating a "hello world" kernel module in linux

October 04, 2009

This is part one of my series on creating a Netfilter module in order to implement a routing protocol in Linux. I’ve broken down the challenge into three steps.

  1. Write a simple kernel module (this article)
  2. Add Netfilter hooks to kernel module
  3. Access packet headers within Netfilter hook
  4. Abstract routing daemon to a user space module (for easier debugging)

This post concerns writing a simple “hello world” kernel module, to illustrate the build process and the installation and uninstallation of the module. My build environment is Ubuntu 8.04, so for those users of other distros, YMMV. I followed a tutorial over at http://www.cyberciti.biz/tips/build-linux-kernel-module-against-installed-kernel-source-tree.html to get  me started.

You’ll need to install build-essential and the linux headers for your distro. I am running Ubuntu 8.04, which runs kernel version 2.6.24-23, so I needed to run: sudo apt-get install build-essential linux-headers-2.6.24-23 This will also provide access to make, which we will need in order to compile the module. With this method, you don’t need the Linux source, just the header files which is great.

There is a much easier way of setting up the Ubuntu build environment using module assistant, to build kernel modules. Follow the guide here and then come back here.

So, now we have the build environment set up, we are going to code up the simple module, implementing the necessary methods, init_module(void) and cleanup_module(void). All the module does is to log these method calls, as a result of installing and removing the module, to /var/log/messages

hello.c

//‘Hello World’ kernel module, logs call to init_module // and cleanup_module to /var/log/messages

// In Ubuntu 8.04 we use make and appropriate Makefile to compile kernel module

#define \_\_KERNEL\_\_
#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>
int init\_module(void)
{
printk(KERN\_INFO "init\_module() called\\n");
return 0;
}
void cleanup\_module(void)
{
printk(KERN\_INFO "cleanup\_module() called\\n");
}

In order to compile the module, we create an associated Makefile, like the following:

Makefile

obj-m := hello.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD)

Then, within our working folder, type make, which will process the Makefile and create a module file, hello.ko

To install the module,type:

sudo insmod hello.ko

To remove the module, type:

sudo rmmod hello.ko

To verify the module has output to the log file, type:

tail /var/log/messages

You should see the relevant log messages init_module() called and cleanup_module() called in this file.

The next post will show how we can create a simple Netfilter installable module based on this hello world kernel module which simply drops any packets, and logs this fact.


👋 I'm Paul Kiddie, a software engineer working in London. I'm currently working as a Principal Engineer at trainline.