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
Pingback: How to compile & recompile linux kernel in Ubuntu (generic way) | Enzam's Blog
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:
Now you can call the system call with “add2(a,b)”.
Awesome. Thanks for posting this.
i followed everything but when i executed the code the sum displayed was wrong. what to do?
What type of error? Please paste some examples, like 2+3, 5+6, etc.
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
If system call returned -1, this means your system call implementation has some error. Please recheck you have done all the steps.
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.
cheers 🙂
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..
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;
}
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 }
I don’t think Enzam is a helpful guy. you should use http://stackoverflow.com/ to get any help.
Sorry for not replying you, I am currently busy with other works. Also http://stackoverflow.com is the best place to get help.
Good artice, thanks
Thanks for reading 🙂
I’m not able to locate the syscall_table_32.S in ubuntu 11.04 , please help
Have you downloaded the source code from http://kernel.org/ ?
Thanks , to given steps to add new system call but how to compile kernel
THank you so much
Hi,
System call returned -1 if I am giving negative values only. What’s my mistake.Please help me. Thank u.
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 🙂
can i use the same steps to add system call in kernal version 3.0.46??
Pingback: Creating my own syscall getting error on compilation of linux kernel...
this link is for linux kernel 3.5
http://blog.techveda.org/index.php/adding-system-calls-linux-kernel-3-5-x/
http://simplyeazy.com/how-to-add-a-system-call-to-linux-kernel/
try this link for fedora.
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
I tried same steps
but System call returned -1
and perror shows Bad Address.
Can you help please?
Pingback: How To Fix 0xabad1dea Errors - Windows Vista, Windows 7 & 8
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