Adding a System Call to Linux Kernel 2.6.x

About ?
This article explains a way to add a system call to Linux kernel (2.6.x).

What is a System Call ?
A system call is an interface between a user-space application and a service that the kernel provides. It is a request for service that a program makes of the kernel. The service is generally something that only the kernel has the privilege to do, such as doing I/O.

System Call Implementation
Prerequisites:

  • You must have root access
  • You may need the following packages for building your kernel build-essential automake autoconf zlib1g-dev libdb4.4-dev libboost-dev libboost-serialization-dev libncurses-dev

Let’s Begin

1. Download the Linux 2.6.x kernel. Get the latest one from http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.39.4.tar.bz2
2. Unzip and untar the downloaded kernel to /usr/src
bzip2 linux-2.6.39.4.tar.bz2
tar -xvf linux-2.6.39.4.tar
3. Create a soft link
ln -s linux-2.6.39.4 linux
This is optional. We can also work with the directory linux-2.6.x.x just created.

4. Create mysyscall.c in the /usr/src/linux/kernel/ directory and add the following lines

#include <linux/linkage>
asmlinkage long sys_add ( int i , int j)
{
return i+j ;
}

Whats the code all about ?
This system call adds two numbers in the kernel space.
asmlinkage: thats there to indicate the code is written in ‘C’ as oppose to C++
sys_add: it is the system call function which adds two numbers

5. Now with your favorite editor edit the Makefile in the current directory. Add the following line

obj-y += mysyscall.o

6. Now that the system call is ready, its time to make necessary changes in some files so that the kernel is aware of this new system call.

Open the file arch/x86/kernel/syscall_table_32.S in a text editor. Go to the end of the
document and add this line
.long sys_add
Now open arch/x86/include/asm/unistd_32.h and find out

#define NR_syscalls 345
And and this this line before it
#define NR_add 345
Change NR_syscalls 345 to
#define N R_syscalls 346

(For 64 bit)
Now edit arch/x86/include/asm/unistd_64.h and add following line at the end of file

#define __NR_add 305
__SYSCALL(__NR_add , sys_add)

Now again in the source folder you will find a folder named include. Open the file
include/linux/syscalls.h and go to the end of the file. Before the line #endif add

asmlinkage long sys_add ( int i , int j) ;

7. Now its time to recompile the new kernel with your own system call added to it. Build the kernel source and install the necessary packages to do so

sudo make
sudo apt-get install kernel-package fakeroot
sudo make−kpkg clean
sudo fakeroot make-kpkg –initrd –append-to-version=-pv kernel-image kernel-headers
sudo dpkg −i ../linux-image-2.6.39.4-pv_2.6.39.4-pv-10.00.Custom_i386.deb

8. To verify your newly build kernel, type in the terminal
uname -r

9. Boot your newly build kernel

Testing !!

Create a file test.c and add the following lines to it.

#inlcude<stdio.h>
#inlclude<linux/unistd.h>
#include<sys/syscall.h>

#define sys_add 345

int main(void)
{
int a,b,c;
printf(“\nKernel Space : Addition\n”);
printf(“Input a:\n”);
scanf(“%d”,&a);
printf(“Input b:\n”);
scanf(“%d”,&b);
c = syscall(sys_add,a,b);
printf(“Sys call returned c: %d\n”,c);
return 0;
}

Save and compile your program and check the result 🙂

Advertisements