Adding A System Call To The Linux Kernel (5.8.1) In Ubuntu (20.04 LTS)
Tags: beginners, tutorial, linux, kernel
Published: 2020-08-12 16:35:19

**In this guide, you will learn how to add a simple system call to the Linux kernel. Check the help sections on the table of contents if you need help with text editors.**

[Section 1 - Preparation](#section-1)
[Section 2 - Creation](#section-2)
[Section 3 - Installation](#section-3)
[Section 4 - Result](#section-4)
[Help - Text Editors](#help-1)
[Help - `nano`](#help-2)

#**Section 1** - Preparation <a name="section-1"></a> 

*In this section, you will download all necessary tools to add a basic system call to the Linux kernel and run it. This is the only part of the entire process where network connectivity is necessary.*

**1.1** - Fully update your operating system.
```bash
sudo apt update && sudo apt upgrade -y
```

**1.2** - Download and install the essential packages to compile kernels.
```bash
sudo apt install build-essential libncurses-dev libssl-dev libelf-dev bison flex -y
```
If would rather use `vim` or any other text editor instead of `nano`, below is an example of how you install it.
```bash
sudo apt install vim -y
```
**1.3** - Clean up your installed packages.
```bash
sudo apt clean && sudo apt autoremove -y
```

**1.4** - Download the source code of the latest stable version of the Linux kernel (*which is 5.8.1 as of 12 August 2020*) to your home folder.
```bash
wget -P ~/ https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.8.1.tar.xz
```
If you have downloaded a newer version of the Linux kernel, refer to [this documentation](https://www.kernel.org/doc/html/latest/process/adding-syscalls.html) to learn about any relevant change made to system calls.

**1.5** - Unpack the tarball you just downloaded to your home folder.
```bash
tar -xvf ~/linux-5.8.1.tar.xz -C ~/
```

**1.6** - Reboot your computer.

#**Section 2** - Creation <a name="section-2"></a> 

*In this section, you will write a basic system call in C and integrate it into the new kernel.*

**2.1** - Check the version of your current kernel.
```bash
uname -r
```
As of 12 August 2020, it should display the following.

`5.4.0-42-generic`

In section 4, it should be different.

**2.2** - Change your working directory to the root directory of the recently unpacked source code.
```bash
cd ~/linux-5.8.1/
```

**2.3** - Create the home directory of your system call.

Decide a name for your system call, and keep it consistent from this point onwards. I have chosen `identity`.
```bash
mkdir identity
```

**2.4** - Create a C file for your system call.

Create the C file with the following command.
```bash
nano identity/identity.c
```
Write the following code in it.
```C
#include <linux/kernel.h>
#include <linux/syscalls.h>

SYSCALL_DEFINE0(identity)

{
	printk("I am Jihan Jasper Al-rashid.\n");
	return 0;
}
```
You can write anything you like here.

Save it and exit the text editor.

**2.5** - Create a Makefile for your system call.

Create the Makefile with the following command.
```bash
nano identity/Makefile
```
Write the following code in it.
```
obj-y := identity.o
```
Save it and exit the text editor.

**2.6** - Add the home directory of your system call to the main Makefile of the kernel.

Open the Makefile with the following command.
```bash
nano Makefile
```

Search for `core-y`. In the second result, you will see a series of directories.

`kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/`

In the fresh source code of Linux 5.8.1 kernel, it should be in line 1073.

Add the home directory of your system call at the end like the following.

```
kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ identity/
```

Save it and exit the editor.

**2.7** - Add a corresponding function prototype for your system call to the header file of system calls.

Open the header file with the following command.
```bash
nano include/linux/syscalls.h
```
Navigate to the bottom of it and write the following code just above `#endif`.
```C
asmlinkage long sys_identity(void);
```
Save it and exit the editor.

**2.8** - Add your system call to the kernel's system call table.

Open the table with the following command.
```bash
nano arch/x86/entry/syscalls/syscall_64.tbl
```
Navigate to the bottom of it. You will find a series of x32 system calls. Scroll to the section above it. This is the section of your interest. Add the following code at the end of this section respecting the chronology of the row as well as the format of the column. Use Tab for space.

``` 
440     common  identity                sys_identity
```
In the fresh source code of Linux 5.8.1 kernel, the number for your system call should be 440.

Save it and exit the editor.

#**Section 3** - Installation <a name="section-3"></a> 

*In this section, you will install the new kernel and prepare your operating system to boot into it.*

**3.1** - Configure the kernel.

Make sure the window of your terminal is maximized.

Open the configuration window with the following command.
```bash
make menuconfig
```
Use **Tab** to move between options. Make no changes to keep it in default settings.

Save and exit.

**3.2** - Find out how many logical cores you have.
```bash
nproc
```
The following few commands require a long time to be executed. Parallel processing will greatly speed them up. For me, it is `12`. Therefore, I will put 12 after `-j` in the following commands.

**3.3** - Compile the kernel's source code.
```bash
make -j12
```

**3.4** - Prepare the installer of the kernel.
```bash
sudo make modules_install -j12
```

**3.5** - Install the kernel.
```bash
sudo make install -j12
``` 

**3.6** - Update the bootloader of the operating system with the new kernel.
```bash
sudo update-grub
```

**3.7** - Reboot your computer.

# **Section 4** - Result <a name="section-4"></a> 

*In this section, you will write a C program to check whether your system call works or not. After that, you will see your system call in action.*

**4.1** - Check the version of your current kernel.
```bash
uname -r
```
It should display the following.

`5.8.1`

**4.2** - Change your working directory to your home directory.
```bash
cd ~
```

**4.3** - Create a C file to generate a report of the success or failure of your system call.

Create the C file with the following command.
```bash
nano report.c
```
Write the following code in it.
```C
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#define __NR_identity 440

long identity_syscall(void)
{
	return syscall(__NR_identity);
}

int main(int argc, char *argv[])
{
	long activity;
	activity = identity_syscall();

	if(activity < 0)
	{
		perror("Sorry, Jasper. Your system call appears to have failed.");
	}
	
	else
	{
		printf("Congratulations, Jasper! Your system call is functional. Run the command dmesg in the terminal and find out!\n");
	}

	return 0;
}
```

You can customize the messages for failure and success anyhow you like.

Save it and exit the editor.

**4.4** - Compile the C file you just created.
```bash
gcc -o report report.c
```

**4.5** - Run the C file you just compiled.
```bash
./report
```

If it displays the following, everything is working as intended.

`Congratulations, Jasper! Your system call is functional. Run the command dmesg in the terminal and find out!`

**4.6** - Check the last line of the `dmesg` output.
```bash
dmesg
```
At the bottom, you should now see the following.

`I am Jihan Jasper Al-rashid.`

#**Congratulations! You have successfully added a system call to the Linux kernel!**

#**Help - Text Editors** <a name="help-1"></a> 

This guide has frequent instances of text editing. You can use whatever gives you comfort. For the purpose of this guide, I have used `nano`. If you would rather use `vim` or any other text editor, simply replace `nano` with either `vim` or any other text editor in all of the commands. If you would rather use a GUI-based text editor, the process is the same. `gedit`, GNOME's default GUI-based text editor, comes bundled with Ubuntu 20.04 LTS.

#**Help - Basic Controls For `nano`** <a name="help-2"></a> 

**Ctrl + O** brings up the interface to save a document. Pressing **Enter** afterwards will complete the process.

**Ctrl + W** brings up the interface to search for anything in a document. You can write anything in here and press **Enter** to jump to it. The result will be highlighted.

**Alt + W** takes you to the next instance, if there is one, after you searched anything once.

**Ctrl + C** cancels any interface.

**Alt + C** turns on the display which shows you the line number based on the position of your cursor.

**Ctrl + X** exits the text editor.