How to add a system call in linux kernel (Ubuntu OS)

This is just a brief description, so read at your own risk.

I have tested & used it. So it should be working. Please install a fresh install of Ubuntu.

This tutorial is for both 32 and 64 bit x86 processors and operating system. I have assumed that you are working in Ubuntu 10.10 and using kernel version 2.6.37.3 . If you are using any other kernel version just replace 2.6.37.3 with your version. I am also assuming you have extracted the source code.

Now let the new system call’s name be “add2”.

1. Now you will find a “arch” folder in the source code folder. 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_add2		/* my code */

2. Now open arch/x86/include/asm/unistd_32.h and find out
#define __NR_prlimit64 340

Add a new line after this:

#define __NR_add2		341

Don’t just close yet. After 3-4 lines, you will find a line like
#define NR_syscalls 341
Change it to

#define NR_syscalls		342

4. Now edit arch/x86/include/asm/unistd_64.h
Find out:
#define __NR_prlimit64 302
__SYSCALL(__NR_prlimit64, sys_prlimit64)

Now after these two lines, add these two lines

#define __NR_add2				303
__SYSCALL(__NR_add2, sys_add2)

5. 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
write this prototype definition line:

asmlinkage long sys_add2(int i,int j);

6. Now find out the kernel folder in the source directory. Create a new empty file in the kernel folder with the name “mysysteamcalls.c” . Add the following codes in the file:

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

7. Now open the Makefile in this folder(/kernel/Makefile) and find out
obj-y += groups.o
Add a new line before this line :

obj-y += mysysteamcalls.o

Ok, this is the edit you need to do to add a new system call. Now compile or recompile the source code and enjoy your new system call.

Here is a sample code to call the system call :

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

//comment the following line if you are using 64 bit, this number is the same used previously
#define sys_add2 341

//comment the following line if you are using 32 bit, this number is the same used previously
#define sys_add2 303

int main(void)
{
    int a,b,c;
    printf("Adding Two Numbers in Kernel Space\n");
    printf("Input a: ");
    scanf("%d",&a);
    printf("Input b: ");
    scanf("%d", &b);
    c = syscall(sys_add2, a, b);
    printf("System call returned %d\n", c);
    return 0;
}

Important note: To add a new system call, you don’t need to create a new file, you can just add a new function in the same “mysysteamcalls.c” file. And if you don’t create a new file you don’t have to do the step 7.

-Enzam

34 responses to “How to add a system call in linux kernel (Ubuntu OS)

  1. Pingback: How to compile & recompile linux kernel in Ubuntu (generic way) | Enzam's Blog

  2. i add the system call according to your description, but i cannot invoke the add2() call in my user space.
    my test file is:

    void main(){
    long i = add2(2,4);
    printf(“i= %ld\n”, i);
    }
    after make, it shows undefined reference to ‘add2’, do i miss anything?

    Thanks

    • We can’t reference system call by their name, you have to reference them by their id(the id we provided previously with #define __NR_add2
      I have updated the page & added a simple code to use the system call, check it out.
      Hope it helps 🙂

      • thanks for your reply, i just have a little more doubt, for read/write file operations, i notice they are implemented in the VFS of the filesystem of the linux. they also use system call to implement the actual operations for read/write and provide the interface for user applications. can we do this like normal read/write operation which use the name directly? for example, add an interface in VFS and implement it as a system call?

      • I’m not sure if i understood your question correctly, but you can always wrap the system call in another function like:

        long add2(long a, long b) {
            return syscall(341,a,b);//for 32 bit
            return syscall(303, a, b); //for 64 bit
        }
        

        Now you can call the system call with “add2(a,b)”.

  3. Thank you for the excellent, detailed, easy to understand post. But I had the same problem as the previous person “mamo”. If I type in any two numbers to add, it will output a minus 1. Any help would be greatly appreciate. Thanks again for all your work.

    Adding Two Numbers in Kernel Space
    Input a: 5
    Input b: 3
    System call returned -1

  4. Thanks for the fast respond. It was my bad, when I restart the computer and run it with the new kernel it has created, the program worked fine. Thanks.

  5. Hello, I am new to Linux and was wondering how can I add a a system call like opening a file, or reading the current time in to the Linux kernel.
    I see on number 6 of your article, you describe how to add two numbers. Can you please give me an example of how can I implement a system call to open a file, read time etc..

  6. Thanks a lot for the awesome explanation. I was trying to add an extra message in the step 6 that you have described above. but there was no luck. can you please look at my code and tell me how can I implement a message in there. Thanks Enzam.

    #include
    #include
    asmlinkage long sys_add2(int i,int j)
    {
    printk(KERN_EMERG “Hello world !”);
    return i+j;
    }

  7. I see my post doesn’t show what I have put in the include. hope the following works.

    01 #include
    02 #include
    03 #include

    04 asmlinkage long sys_add2(int i,int j)
    05 {
    06 printk(KERN_EMERG “Hello world !”);
    07 return i+j;
    08 }

  8. Hi, can you produce a new adding a system call tutorial?.. for linux kernel 3.5.4 because I can’t find any of those directory/files and also what’s the correct syntax for a system call?..

    is this even right? :

    #include

    asmlinkage int helloworld(){
    printk(KERN_EMERG “Hello World!!”);
    return 0;
    }

    would this work?.. or will it cause error?..

    • Hi there, sorry for not being able to help you with this, I am currently busy with other things. Hope you will experiment and will eventually figure it out 🙂

  9. Pingback: Creating my own syscall getting error on compilation of linux kernel...

  10. Beautiful, as you said I had to do it more than 11 times to get the hang of working with system call, but very well documented.

    Some pointers since this doc has not been updated for a while.
    1) recompiling instructions kill the Installed linux source removing and recompiling is introducing UUID not found error.trying alternatives for the same.
    2) You did not tell how to download the source for the current kernel source (The first step is to download the source code of the Linux kernel), login to the kernel source that you want to compile and use

    apt-get source linux-image-$(uname -r)

    Overall one hell of a doc to blindly follow and get the system call working 🙂

    Thank you

  11. Pingback: How To Fix 0xabad1dea Errors - Windows Vista, Windows 7 & 8

  12. hi am not able to compile it is showing m the error “error: conflicting types for ‘syscall_trace_enter’
    asmregparm long syscall_trace_enter(struct pt_regs *regs)”

    please help if u can

Leave a reply to wordpress Cancel reply