Adding a quick System Call to the Linux Kernel

Jeremy Philemon
5 min readFeb 16, 2018

For consistency sake, I suggest using a compiled kernel version of 4.7.1 if you’re following this guide meticulously line by line.

Henceforth, it is assumed that you’re done with compiling your Linux Kernel from source with the kernel version of your choice, you know the location of the compiled/extracted kernel source directory, and have successfully booted into the said version from your grub bootloader.

Now switch into the compiled source directory, eg: cd linux-4.7.1/
Note: The location of this source directory varies with respect to the location you’ve extracted and compiled your kernel

Define a new System Call, sys_hello()

Create a new directory, mkdir hello and change into the said directory by cd hello Consequently, create a new C file in this directory in order to add the definition of our system call by nano hello.c (I’m using the nano editor, while you can use any text editor of your choice).

Add the following code to your new C file

#include <linux/kernel.h>asmlinkage long sys_hello(void) {
printk(“Hello, world!\n”);
return 0;
}

Note that here printk("...") is a kernel exclusive function that prints to the kernel’s log file, which can be accessed by the command dmesg

Add the hello directory to the kernel’s Makefile

Similarly, create a new Makefile in the same folder by nano Makefile with the following line obj-y := hello.o This Makefile specifies the objects to be built and added to the source during the next kernel recompilation.

But before that could happen, we need to make sure that the parent Makefile points to this directory. So let’s switch back to the previous directory by cd .. which will take us back to the linux-4.7.1/ directory. Now we shall edit the parent Makefile by nano Makefile

Here we should look for the line that goes like
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
and append the hello/ directory to the variable so it looks like
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ hello/

Pro tip: So if you’re using the nano editor, you can use CTRL+W to fire up the search console (technically know as Where Is) to find the respective line and make the changes.

This amendment will tell the compiler that the source files of our new system call sys_hello() are present in the hello/ directory.

So to recap, the compiler’s flow during a sudo make will look something like — Makefile is executed and since the hello/ directory is now listed, it will search for another Makefile in the said directory for further instructions about which objects to compile.

Add the new system call into the System Call table

Since I’m working on a 64-bit system, I will have to alter the syscall_64.tbl file.

To do this, I edit the table by nano arch/x86/entry/syscalls/syscall_64.tbl and scroll down till I find the number of the last system call before those starting from 512.

In my case, that’s 328. So my new System Call’s number should be 329.

Now add the line 329 64 hello sys_hello after the 328th System Call to provision our newly created System Call. Remember this number 329 cause we’ll need it in a few minutes.

Add the new System Call in the System Call header file

Now head back to the source directory linux-4.7.1 and change directories with cd include/linux/ Furthermore, nano syscalls.h and add the line asmlinkage long sys_hello(void); at the end of the file just before the #endif statement.

This defines the prototype of the function of our System Call. asmlinkage is a keyword used to indicate that all parameters of the function would be available on the stack.

Recompile the kernel

Switch over to the source directory linux-4.7.1/ and execute the following command sudo make -j4 modules_install install and watch your terminal throw a bunch of INSTALL lines till you reach a successful quiet completion.

For the system to now use the newly configured kernel, reboot.

Test the System Call

Like we did previously, create a C program in your home folder by nano userspace.c and add the following code

#include <stdio.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>
int main() {
long int shoutout = syscall(329);
printf(“System call sys_hello returned %ld\n”, shoutout);
return 0;
}

Note that this is where you’ll need to use the number of the newly created System Call — 329.

Finally, let’s compile the program using gcc userspace.c and given that there are no errors during this compilation, run the said program using ./a.out

If all steps were followed correctly, System call sys_hello returned 0 gets printed onto the console. If it shows -1 instead of 0, then something’s wrong so you’d have to go back, debug and try again.

Since earlier we used the kernel function printk("...") that prints to the kernel’s log, we shall enter dmesg to check if the message has been sucessfully printed.

--

--