How To Add A System Call in Linux Kernel
How To Add A System Call in Linux Kernel
GROUP 2
Syed Shabbir Haider (110594)
Ahad Tanvir (110606)
Kaywan Rauf (110935)
Following are the steps for adding a system call in the Linux kernel:
to download the source for the particular version of your kernel distribution type this command in the terminal
The source of that particular kernel will begin to download, it will take some time depending upon the speed of your internet
connections.
You can also go to www.kernel.org to download the kernel of particular version or the latest stable kernel from the kernel
archives. As I mentioned if youre not interested in working on the particular kernel version of your Linux distribution, you can
download the latest stable kernel or any version that you wish. The most recent distributions of Linux such as Ubuntu,
Backtrack etc. have a big kernel, so if you are using any recent version of Linux then it is advisable to download a smaller
version of kernel.
Tip: If you want to use a kernel other than your Linux distribution, try to choose a kernel which is smaller in size, because
bigger the kernel more it will take to compile it.
Once you downloaded your kernel source, next step is to extract it. For this purpose go to your home folder or root directory,
you would see a zipped file named linux-source-x.y.z.tar.bz (where x, y , z indicates the version such as linux-source3.2.0),
Right click on the file and then click Extract here. I have extracted this source in the home folder(root directory) for my
convenience so that I can easily access it, you may extract it anywhere.
After you extract, you would be able to see a folder named linux-source-x.y.z (where x, y , z indicates the version such as
linux-source3.2.0),
Now the source of the kernel is available to you, you would be able to browse and view the files and make changes.
You can also extract this zipped file by typing the following command in the terminal,
tar xvzf linux-source-x.y.z.tar.bz(where x, y , z indicates the version such as linux-source3.2.0),
In the folder linux-source-x.y.z (where x, y , z indicates the version such as linux-source3.2.0), go the file
arch/x86/kernel/syscall_table_32.S, and add the following line
.long sys_hello
syscall_table_32 is the system call table which consists of assemble instructions in which record of all the system calls in
the system is kept. You can assume it as an array having consecutive locations, on each location theres an entry of the system
call. We have the entry of our system call at the end of this table, if we add another system call it will be added in the end as
well and so on(just like filling the consecutive locations of an array). sys_call_table is the base pointer and points to the start of
the array, that is, to the zero entry of an array in other words. If a user-space program invokes the sendmssg system call, the
number passed is 345. The dispatcher routine adds this number to the sys_call_table base and arrives at the three forty fifth
entry that holds the address of sys_sendmmsg.
Define Macros associated with the system call:
In the linux-source-x.y.z folder go the file arch/x86/include/asm/unistd_32.h, you would notice that a number is been
defined with each system call, that number is called macro. Macro is a constant associated with each system call which
indicated the location of the system call in the system call table or in other words it simply defines the system call number.
Add the following line
#define __NR_hello 349
This is the definition of our system call, and also increment the value of the NR_SYSCALLS by 1, since we are adding one
system call
Now go the file arch/x86/include/asm/unistd_64.h and add the definition of you system call,
#define __NR_hello 312
__SYSCALL(__NR_hello, sys_hello)
Now to the file include/linux/syscalls.h, add the prototype of the system call.
asmlinkage long sys_hello(void);
Now in the folder linux-source-x.y.z (where x, y , z indicates the version such as linux-source3.2.0), create a new folder and
name that folder hello. In that folder create a file named hello.c, and add the following code to that file.
#include <linux/kernel.h>
asmlinkage long sys_hello(void)
{
printk("Hello world\n");
return 0;
}
obj-y := hello.o
This will create the object file of the system call to be execute it. Kernel will use this file to build the system call. Now go the
folder linux-source-x.y.z (where x, y , z indicates the version such as linux-source3.2.0), and look for a make file. Open that
file and edit the following line to the text shown in the image below
core-y
:= kernel/ mm/ fs/ ipc/ security/ crypto/ block/
This is our system call which kernel will execute. asmlinkage is itself is afunction which is must for the kernels otherwise the
system call wont work, and kernel wont be able to distinguish that either it is a user program or a kernel program. You can
see printk statement in the body of that function. printk is just like printf or cout which displays the output, but printf and
cout display output on the console window, unlike these two statements printk will write the output of the system call to the
kernel log. On execution , the system call returns a long integer, indicating the status of the system call, for example if system
call returned 1, then that means that system call was terminated prematurely, or if it returns -1 it means system call does not
exist( kernel was unable to locate it in the system call table), if it returns 0, that means it executed normally as it should.
Now in the same directory (hello folder), create another file, and name it Makefile, and add the following text to it.
10
11
This will make sure that our hello system call is in hello directory and it is is also compiled and build when we will compile
our kernel.
Now we have added the system call, we need to compile our kernel and test this system call.
Compiling the kernel:
For compiling the kernel following three packages must be installed on your system.
gcc compiler (latest version)
ncurses development kit
system packages(updates)
For installing gcc compiler type the following command in the terminal
sudo apt-get install gcc
For installing ncurses development packages type the following in the terminal
12
Something like that will be displayed on the screen while compiling the kernel
13
Tip:
If you have multi-core, multi-processor machine then you can reduce the compile time of the kernel by making use of cores
available. For compiling on different cores type the following to the terminal
#include
#include
#include
#include
<stdio.h>
<linux/kernel.h>
<sys/syscall.h>
<unistd.h>
#define __NR_hello 312 //349 if you are running a 32bit kernel and following my
tutorial
long hello_syscall(void)
{
return syscall(__NR_hello);
}
After rebooting run the following test program to check either our system call is working fine or not.
14
15
As I mentioned earlier that you would not be able to see the output of the system call Hello World on the console
window, the output of that system call is written in the kernel log.
To view the kernel log type the following command in the terminal:
16
dmesg
17
Most probably, the output of the system call will be written at the end of the log. In the image you would notice that Hello
world appeared two times. This is because I ran my test.c program twice or in other words I invoked the hello system call two
times, that means every time you invoke the system call, its output is going to be written on the kernel log. Thats why Hello
word appeared twice on the log can be seen.
18