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

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

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

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_DESCRIPTION("Nothing serious, just for fun!");

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

	return hwkm_entry_point();

	return hwkm_exit_point();


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 

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

	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