I am trying to write a system call of my own. It would just return the current time. I know the concept of what should I do and I did go through a couple of links like these:
But I am still confused and have not got the desired result. The kernel is not compiling and its crashing due to problems. I have tried it on debian latest stable release of 3.X.X
Could someone point me out to a clean hello world
kind of program to develop system calls?
EDIT
To the below answer, here are my problems:
File 3: linux-x.x.x/arch/x86/kernel/syscall_table_32.S
is not found in my linux folder. I had to improvise and so modified the following file: linux-x.x.x/arch/x86/syscalls/syscall_64.tbl
The above (1) new file mentioned had different pattern of <number> <64/x32/common> <name> <entry point>
and my entry was `313 common
The kernel image did compile successfully, but I couldnt call the function. It gives an undefined reference" error
when i compile it with gcc. Why?
This is just example how to write a simple kernel system call.
Consider the following C function system_strcpy() that simply copies one string into another: similar to what strcpy() does.
#include<stdio.h>
long system_strcpy(char* dest, const char* src)
{
int i=0;
while(src[i]!=0)
dest[i]=src[i++];
dest[i]=0;
return i;
}
Before writing, get a kernel source tar and untar it to get a linux-x.x.x directory.
File 1: linux-x.x.x/test/system_strcpy.c
Create a directory within the linux-x.x.x, named test
and save this code as file system_strcpy.c
in it.
#include<linux/linkage.h>
#include<linux/kernel.h>
asmlinkage long system_strcpy(char*dest, const char* src)
{
int i=0;
while(src[i]!=0)
dest[i]=src[i++];
dest[i]=0;
return i;
}
File 2: linux-x.x.x/test/Makefile
Create a Makefile
within the same test
directory you created above and put this line in it:
obj-y := system_strcpy.o
File 3: linux-x.x.x/arch/x86/kernel/syscall_table_32.S
Now, you have to add your system call to the system call table.
Append to the file the following line:
.long system_strcpy
NOTE: For Kernel 3.3 and higher versions.
*Refer:linux-3.3.xx/arch/x86/syscalls/syscall_64.tbl*
And in there, now add at the end of the following series of lines:
310 64 process_vm_readv sys_process_vm_readv
311 64 process_vm_writev sys_process_vm_writev
312 64 kcmp sys_kcmp
313 64 system_strcpy system_strcpy
The format for the 3.3 version is in:
number
abi
name
entry point
File 4: linux-x.x.x/arch/x86/include/asm/unistd_32.h
NOTE: This section is redundant for 3.3 and higher kernel versions
In this file, the names of all the system calls will be associated with a unique number. After the last system call-number pair, add a line
#define __NR_system_strcpy 338
(if 337 was the number associated with the last system call in the system call-number pair).
Then replace NR_syscalls
value, stating total number of system calls with (the existing number incremented by 1) i.e. in this case the NR_syscalls
should've been 338 and the new value is 339.
#define NR_syscalls 339
File 5: linux-x.x.x/include/linux/syscalls.h
Append to the file the prototype of our function.
asmlinkage long system_strcpy(char *dest,char *src);
just before the #endif
line in the file.
File 6: Makefile at the root of source directory.
Open Makefile
and find the line where core-y
is defined and add the directory test
to the end of that line.
core-y += kernel/ mm/ fs/ test/
Now compile the kernel. Issue:
make bzImage -j4
Install the kernel by executing the following command as root(or with root permissions):
make install
Reboot the system.
To use the recently created system call use:
syscall(338,dest,src);
(or syscall(313,dest,src);
for kernel 3.3+) instead of the regular strcpy
library function.
#include "unistd.h"
#include "sys/syscall.h"
int main()
{
char *dest=NULL,*src="Hello";
dest=(char*)malloc(strlen(src)+1);
syscall(338,dest,src);//syscall(313,dest,src); for kernel 3.3+
printf("%s \n %s\n",src,dest);
return 0;
}
Instead of numbers like 313,etc in syscall
, you can also directly use __NR_system_strcpy
This is a generic example. You will need to do a little experimentation to see what works for your specific kernel version.
The above answer does not work for kernel 3.5.0 and 3.7.6, producing undefined reference compiling error. To fix the problem linux/syscalls.h should be included in system_strcpy.c instead of linux/linkage.h. Also, it's better to use SYSCALL_DEFINE2(strcpy, dest, src) to define a system call.