Adding a Hello World System Call to Linux Kernel

In this blog, I’m going to tell you how to add a system call to the Linux kernel. It is like a Hello World program for System calls. :P

Adding Hello World to System Call in Linux Kernel

Q. Why write this blog?

There is already an awesome blog by tssurya on how to add system call to the linux kernel. You may find it here.

The problem is that the blog is 4 years old and has now become outdated causing problems with the modern operating systems.

I learned it the hard way by getting errors and resolving them, re-making kernel again and again until the kernel was loaded and it worked. :’)

So I have written this blog so that you don’t have to face these problems when you try it.

System Details

I am currently using ubuntu 16.04 (64 bit) system with dual cores. I currently have kernel 4.13.0–36-generic.

To know which kernel you have type on terminal uname -r which will give your kernel version.

Pro Tip: type sudo -s in your terminal before executing the upcoming commands so that you need not write sudo again and again in the terminal, it will give you a super user terminal session.

You may copy the commands and code directly from this blog to avoid mistakes.

1. Download the kernel source:

In your terminal type the following command:

wget https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.17.4.tar.xz

As my kernel version was 4.13, I downloaded a kernel of higher version (4.17.4), this way the kernel gets automatically updated when you reboot the system after compiling.

Also, make sure to write appropriate v4.x or anything else based on the version series you type.

wget command : GNU Wget is a free utility for non-interactive download of files from the Web.

2. Extract the kernel source code

sudo tar -xvf linux-4.17.4.tar.xz -C/usr/src/

tar — Tar stores and extracts files from a tape or disk archive.

-x — extract files from an archive

-v — requested using the –verbose option, when extracting archives

-f — file archive; use archive file or device archive

-C — extract to the directory specified after it.(in this case /usr/src/)

Now, we’ll change the directory to where the files are extracted:

cd /usr/src/linux-4.17.4/

3. Define a new system call sys_hello( )

  • Create a directory named hello/ and change the directory to hello/:
mkdir hello
cd hello

Create a file hello.c using your favourite text editor:

gedit hello.c

write the following code in the editor:

Content of hello.c file

printk prints to the kernel’s log file.

  • Create a “Makefile” in the hello directory:

gedit Makefile

and add the following line to it:

obj-y := hello.o

This is to ensure that the hello.c file is compiled and included in the kernel source code.

Note: There is no space in between“obj-y”.

4. Adding hello/ to the kernel’s Makefile:

Go back to the parent dir i.e. cd ../ and open “Makefile”

gedit Makefile

search for core-y in the document, you’ll find this line as the second instance of your search:

core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/

Add ‘hello/’ to the end of this line:

core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ hello/

Note: There is a space between “block/” and “hello/”. (Doing such a mistake may cause errors in further steps)

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

5. Add the new system call to the system call table:

If you are on a 32-bit system you’ll need to change ‘syscall_32.tbl’. For 64-bit, change ‘syscall_64.tbl’.

Run the following commands in your terminal from linux-4.17.4/ directory:

cd arch/x86/entry/syscalls/
gedit syscall_64.tbl

You’ll get a file like the following in your editor:

syscalls_64.tbl

Go to the last of the document and add a new line like so:

548       64        hello          sys_hello

Note:

  • Here I’ve written 548 because in the previous line the number entry was 547. Remember this number it will be used in the later steps.
  • Also, note that I’ve written 64 in my system because it is 64 bit. You may have to write i586 or x32. For knowing what is to be written check in this file itself in many of the lines you may find entries like so:
64 written at 310, 311 and 322 line numbers

This will tell you whether to write i586 or something else.

Save and exit.

6. Add new system call to the system call header file:

Go to the linux-4.17.4/ directory and type the following commands:

cd include/linux/
gedit syscalls.h

Add the following line to the end of the document before the #endif statement:

asmlinkage long sys_hello(void);

After this your file will look like so:

Save and exit.

This defines the prototype of the function of our system call. “asmlinkage” is a key word used to indicate that all parameters of the function would be available on the stack.

7. Compile the kernel:

Before starting to compile you need to install a few packages. Type the following commands in your terminal:

sudo apt-get install gcc
sudo apt-get install libncurses5-dev
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install libssl-dev
sudo apt-get install libelf-dev
sudo apt-get update
sudo apt-get upgrade

to configure your kernel use the following command in your linux-4.17.4/ directory:

sudo make menuconfig

Once the above command is used to configure the Linux kernel, you will get a pop up window with the list of menus and you can select the items for the new configuration. If your unfamiliar with the configuration just check for the file systems menu and check whether “ext4” is chosen or not, if not select it and save the configuration.

Now to compile the kernel you can use the make command:

sudo make

Pro Tip: The make command can take a lot of time in compiling, to speed up the process you can take advantage of the multiple cores that our systems have these days. Simply type,

sudo make -jn

where n is the number of cores that you have in your linux system. For example if I have a Quad core(4) processor, I’ll write:

sudo make -j4

this will speed up my make process 4x times. ;)

This might take several hours depending on your system. It took me 2–3 hours to get this compiled.

8. Install / update Kernel:

Run the following command in your terminal:

sudo make modules_install install

It will create some files under /boot/ directory and it will automatically make a entry in your grub.cfg. To check whether it made correct entry, check the files under /boot/ directory . If you have followed the steps without any error you will find the following files in it in addition to others.

  1. System.map-4.17.4
  2. vmlinuz-4.17.4
  3. initrd.img-4.17.4
  4. config-4.17.4

Now to update the kernel in your system reboot the system . You can use the following command:

shutdown -r now

After rebooting you can verify the kernel version using the following command:

uname -r

It will display the kernel version like so:

4.17.4

9. Test system call:

Go to your home(~) directory using the following commands and create a userspace.c file.

cd ~
gedit userspace.c

Write the following code in this file:

userspace.c file content

Note: Remember I told you to keep in mind the number of system call that we wrote in syscalls_64.tbl? In my case the number was 548. Write that same number in your userspace.c file as an argument in syscall() function.

Now, compile and run the program:

gcc userspace.c
./a.out

If all the steps are done correctly you’ll get an output like below:

System call sys_hello returned 0

Now, to check the message of your kernel run the following command:

dmesg

This will display Hello world at the end of the kernel’s message.

This ends the process of Adding a Hello World System Call to your Linux Kernel.

Extras:

  1. Keep in mind that this assignment may require upto 40 GB of hard disk storage, so make sure you have that.
  2. In case after the completion uname -r still shows generic kernel version. Then you may have to manually change the kernel in your grub. To do so, you may refer to this link.

Credits:

I would like to thank Tssurya for writing the blog. My blog is just an updated version of what he wrote due to the changes that happen from time to time in OS and systems. :)

Also, I would like to thank my dear friend Abhay for helping me out solve the errors while I was doing this assignment. :P


Give this post claps+ if you like it. ;)

You can also get in touch with me on Twitter at @ShrimalAnubhav, look at my portfolio, or find me on LinkedIn and Facebook. I’d love to hear from you.