A Basic Linux Kernel Module with Assembly Language

The last post was an overview of a basic Linux kernel module in C. In this post I will look at a basic Linux kernel module, but using x64 Assembly Language for the module with C as a wrapper in order to build it successfully, not an original idea and quite a common way to go about things 🙂

From a clean Debian installation run the following to setup the correct environment for building a kernel module.

root@debian:~# apt-get install build-essential linux-source linux-headers-amd64

This is the Assembly Language logic for the module and will handle printing debug messages on entry to and exit from the kernel.

File: asm-lkm.s

global 	hwkm_entry_point
global 	hwkm_exit_point

section .text
	extern 	printk

hwkm_entry_point:
	push    rbp
 	mov     rbp, rsp
	xor     rax, rax
	mov     rdi, msg_on_entry
	call    printk
	xor     rax, rax
	mov     rsp, rbp
	pop     rbp
	ret

hwkm_exit_point:
	push    rbp
	mov     rbp, rsp
	xor     rax, rax
	mov     rdi, msg_on_exit
	call    printk
	xor     rax, rax
	mov     rsp, rbp
	pop     rbp
	ret

section	.data
	msg_on_entry    db      "Hello everybody peeps!", 0xa, 0x0
	msg_on_exit     db      "So long and thanks for all the fish!", 0xa, 0x0

This C code will make registering the module a lot simpler than trying to accomplish the same thing in Assembly Language. It simply pulls in the references to the relevant functions from the Assembly Language object and jumps to them on return from both the _init and _exit functions.

File: asm-lkm-wrapper.c

#include <linux/module.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("YourName");
MODULE_DESCRIPTION("Nothing serious, just for fun!");

extern int hwkm_entry_point(void);
extern void hwkm_exit_point(void);

int 
wrapper_init(void)
{
	return hwkm_entry_point();
}

void
wrapper_exit(void)
{
	return hwkm_exit_point();
}

module_init(wrapper_init);
module_exit(wrapper_exit);

To build the module is actually quite simple as well, as can be seen below.

File: Makefile

obj-m := hwkm.o
hwkm-objs := asm-lkm-wrapper.o asm-lkm.o 

all:
	nasm -felf64 -o asm-lkm.o asm-lkm.s
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD)

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

The main module object will be called hwkm (Hello World Kernel Module). The hwkm-objs are the object files that are required to build the main kernel module. The Assembly Language module is built first due to the dependency on it by the C wrapper code, then the module is built in the normal way.

Use the following to build and test the kernel module, the module should be built as root.

root@debian:/projects# make
nasm -felf64 -o asm-lkm.o asm-lkm.s
make -C /lib/modules/3.16.0-4-amd64/build M=/projects
make[1]: Entering directory '/usr/src/linux-headers-3.16.0-4-amd64'
make[1]: Entering directory `/usr/src/linux-headers-3.16.0-4-amd64'
  LD      /projects/basic-linux-kernel-module-in-asm/built-in.o
  CC [M]  /projects/basic-linux-kernel-module-in-asm/asm-lkm-wrapper.o
  LD [M]  /projects/basic-linux-kernel-module-in-asm/hwkm.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /projects/basic-linux-kernel-module-in-asm/hwkm.mod.o
  LD [M]  /projects/basic-linux-kernel-module-in-asm/hwkm.ko
make[1]: Leaving directory '/usr/src/linux-headers-3.16.0-4-amd64'

root@debian:/projects# insmod hwkm.ko
root@debian:/projects# tail -f /var/log/messages
Aug 29 16:37:28 debian kernel: [35520.386452] Hello everybody peeps!

root@debian:/projects# rmmod hwkm.ko
root@debian:/projects# tail -f /var/log/messages
Aug 29 16:37:45 debian kernel: [35536.970390] So long and thanks for all the fish!

This is another post that is again very brief in order to lay some groundwork for further fun, profit and/or research.

Link to Github repo

2 thoughts on “A Basic Linux Kernel Module with Assembly Language

  1. `extern` is the default for function prototypes and hence is superfluous and usually not used, see the linux kernel to convince yourself of this fact.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s