your own system call in 5 easy steps

You *might* want to write your system call for various reasons

Assuming the path to your kernel source is "L". Create a new folder L/mysyscall. Inside the folder create the source file mysyscall.c and a Makefile

Step 1. Changing the System Table
L/arch/x86/kernel/syscall_table_32.S

Add your system call at the end of the file.

.long sys_new_system_call

Step 2. Changing the unistd.h
L/linux/include/asm-x86/unistd_32.h

Add your system call at the end of the existing list and append the next number

#define __NR_new_system_call XXX

Where XXX is the existing system call number plus 1. Also update the total system calls (as you just added another)
#define __NR_syscalls XXY
Where XXY is XXX+1

Step 3: Changing syscalls.h
L/include/linux/syscalls.h

Add the declaration of your system call at the end.
asmlinkage long new_system_call (whatever params you want to pass)

Step 4: Changing the kernel Makefile
Add the new folder to the kernel compile

core-y += /kernel /blah /blah /blah /mysyscall

Step 5: Write your system call

Write whatever crap you want to write inside the mysyscall.c file

asmlinkage long new_system_call (whatever params you want to pass)
{
  // whatever you want to do
}


Change the makefile as well and add the following line

obj-y := mysyscall.o

Compile your kernel and test the system call from a user level program. You can create a header file that the user space program can use.

/* header.h */
#include < linux/unistd.h >
#define __NR_new_system_call XXX

/* if you system call returns int and takes no parameter
* use this macro
*/
_syscall0(int,new_system_call)

/* Otherwise, depending on the number of parameters
* being passed use the _syscallN macro, N being the no
* of params, like
_syscall1(int, new_system_call, int)

*/

Last thing to do is to test the code:

/* test client */
#include "header.h"

int main (void)
{
  printf ("System call returned %d \n", new_system_call());
  return 1;
}


NOTE
Starting around kernel 2.6.18, the _syscallXX macros were removed from header files supplied to user space. Instead we need to use syscall() function.

printf ("System call returned %d \n", syscall (__NR_new_system_call, params_if_any));

or, make the following changes in the header.h

/* header.h */
#include < linux/unistd.h >
#include < sys/syscall.h >
#define __NR_new_system_call XXX

long new_system_call (params_if_any)
{
  return syscall (__NR_new_system_call, params_if_any);
}

No comments: