This semester we have an operating systems course, which requires us to compile the
linuxkernel and add a system call. However, the tutorial our teacher provided is based on the2.xkernel; with newerGCCversions, compiling that kernel is basically impossible.Also, replacing the kernel directly on the host system could cause trouble for users, so none of the operations in this tutorial require modifying the original system. All system call testing is done inside the
qemuvirtual machine.If you’re not familiar with
Linux, you can use thegediteditor to create and edit files.The important host environment versions are listed below.
- Kernel version to compile:
4.10.3(stable release of 2017-03-15) - Host Linux version:
4.10.2-1-ARCH - Compiler version:
gcc 6.3.1 qemuversion:2.8.0busyboxversion:1.26
This tutorial has a limited shelf life. If the future
Linuxkernel structure differs from this, do not follow it, or contact me to take the tutorial down, so it won’t mislead anyone.
Compiling the Linux Kernel
Downloading the Kernel

- Extract after downloading
1 | xz -d linux-4.10.3.tar.xz |

- Compile and boot
If you use
Ubuntu, any problem during compilation can be solved by simply searching online.
1 | make menuconfig # defaults are fine; trimming options speeds up compilation |
It took me about 15 minutes (CPU: i5-4200M).
Booting Our Compiled Kernel with qemu
What we just compiled is only a
linuxkernel. It is very powerful, but a kernel alone cannot be called a system. Here we usebusyboxto build a root filesystem. To make things easy, I provide a ready-made system image here.
Download it here: world.img
- Basic
qemuusage (we are in the kernel directory now)
1 | qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage \ |
- Explanation of the parameters
1 | -kernel arch/x86_64/boot/bzImage # specify the kernel |
After a successful boot it looks like this — a minimal linux system is now set up.

Adding the System Call
Defining the New System Call
- Make sure you are in the kernel directory
1 | mkdir $KERNEL/hello |
- Create the file
hello.cyourself; its content is shown below (view files withcat)
version_changed: 2019-08-30 Thanks to a junior student for the correction: defining sys_hello in hello.c is problematic. The
SYSCALL_DEFINEform should be used instead. This issue is related to CVE-2009-0029; I haven’t studied it deeply. Still, custom system calls had better stay consistent with the kernel’s other system calls.Please change
asmlinkage long sys_hello(int arg0)in the code below toSYSCALL_DEFINE1(hello, arg0)

Adding It to the System Call Table
- Modify
syscall_64.tbl
In 4.10.3 this file is at arch/x86/entry/syscalls/syscall_64.tbl.
We add our own system call at the end of the file.

- Modify
syscalls.h
In 4.10.3 this file is at include/linux/syscalls.h.
Again we add our system call at the end.

Adding It to the Kernel Build Makefile
- Create a
Makefilein thehellodirectory with the following content

- Modify the global main
Makefile

The global main
Makefileis theMakefilein the kernel directory, around line 900-something, with this line:
1 | core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ |
Now we change it to the following, i.e. adding the hello folder:
1 | core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ hello/ |
Recompiling the Kernel
After the work above you can recompile the kernel: just
make -j4, no need formake menuconfig. Since the previous compilation left intermediate files, this would normally be fast. Unfortunately, after adding a system call basically the whole kernel must be recompiled — please be patient.
Testing Our New System Call
For a program that uses the system call, we first need to put the program into the root filesystem so it can be executed inside the
qemuvirtual machine. Therefore, we first mount the root filesystem to a local directory, then add the compiled test program to the root filesystem — that is, copy it into that directory.
Mounting the world.img File on the Host
1 | mkdir world_mount # new folder; the program will be copied here |
As shown below:

Writing a Program That Uses the System Call
- The system call program
The system call number we added is
551, and it takes one int argument, so the function here issyscall(551, 24). If in doubt, refer to the earlierhello.cfile — comparing the two makes it easier to understand. Thecall.cfile is shown below.
1 |
|
- After saving, compile directly
1 | gcc -o call call.c -static |
- Copy the program into the root filesystem
1 | sudo cp call world_mount/ |
- Boot the system with
qemu
1 | qemu-system-x86_64 -kernel arch/x86_64/boot/bzImage \ |
The booted system looks like the figure below. Run the program with
./call. Since our system call uses theprintkfunction, the kernel outputs the message, which can be viewed withdmesg— and there you’ll see the printed content.

- The final directory structure looks roughly like this
1 | . |
References
LICENSE:
Copyright © 2016 corvo. Commercial use without permission is prohibited. Please credit the source when reposting.