[ Curiosity,Experimentation ]

Random stuff from the parallel universe of Ones and Zeroes

Archive for November, 2010

Implementing a System call in Linux Kernel 2.6.35

Posted by appusajeev on November 13, 2010

As we know, System calls are a set of services/functions provided to the programmer by the OS. These functions can be invoked in any language that provide some interface to the System call mechanism of the OS. Some common linux system calls are open,read,write etc.
While executing a system call, the calling process moves from user space to kernel space and back to user space when its completes executing the call.

There are around 338 system calls in linux kernel  2.6.35.7 by default. Presented here a howto on adding a new one into the kernel, a 339th one so that it will be available globally for any program. As example, we will implement the strcpy function as a system call so that it can be used without including string.h.

Obviously, you need the kernel source tree since some kernel modification is involved. Get it from kernel.org (any kernel version higher than 2.6.35.7 would work fine )and untar it to get linux-2.6.35.7. The paths used below all will be relative to this path.
We need to edit 4 files and 2 files need to be created.

The Code

First, lets start off writing the code for strcpy. We need to include the file linux/linkage.h because it contains the macro asmlinkage which means that the system call expects the arguments on the stack and not in registers. Printk is the kernel alternative of printf, but with certain peculiar properties.

Code for the system call

Code for the system call

<1>” tells printk that we are giving that message the highest priority.

Create a folder named ‘test’ in the root of linux source directory and save this file as strcpy.c in that directory. Create a Makefile in that directory containing only the line.

obj-y:=strcpy.o

Thus, now the strcpy.c file and Makefile are present in

linux-2.6.35.7/test/strcpy.c
linux-2.6.35.7/test/Makefile

The Edits

The following files need to be edited.

1. linux-2.6.35.7/arch/x86/kernel/syscall_table_32.S

Append to the file the following line

.long sys_strcpy

linux-2.6.35/arch/x86/kernel/syscall_table_32.S

linux-2.6.35/arch/x86/kernel/syscall_table_32.S

2. linux-2.6.35.7/arch/x86/include/asm/unistd_32.h

This file contains the unique number associated with each system call. We can see the names of all the system calls and the number associated with each. After the last system call-number pair (around line 345), add a line

#define __NR_strcpy  338

(if 337 was the number associated with the last system call).
Then replace NR_syscalls directive denoting the total number of system calls by the previous number incremented by 1 ie the new value is

#define NR_syscalls 339

Note down the number 338, we need it later.

linux-2.6.35/arch/x86/include/asm/unistd_32.h

linux-2.6.35/arch/x86/include/asm/unistd_32.h

3. linux-2.6.35.7/include/linux/syscalls.h

This file contains the prototype of all the system calls. Here we append to the file the prototype of our function.
ie. We add  the line

asmlinkage  long sys_strcpy(char *dest,char *src);


linux-2.6.35/include/linux/syscalls.h

linux-2.6.35/include/linux/syscalls.h

4. Makefile

Open Makefile present in the root of source directory and find the area where core-y is defined and add the folder test to the end of that line as shown below

Makefile

Makefile

Next compile the kernel. Assuming you are familiar with kernel compilation, execute
make bzImage  –j4
The last argument is optional and is intended to speed up compilation on dual core CPUS
Once compilation is complete, install the kernel by executing the following command with root permission
make install
Once the kernel image is installed to /boot, reboot the system.

Testing

Now we need to check the newly done system call. Run the code below and feel the satisfaction 🙂

System call test

System call test

The kernel has performed the strcpy for us. Cool ! isn’t it

Note:
Execute the command dmesg now, you can see done printed in the last. Printk by default doesnt  print to the terminal. It writes to the kernel ring buffer which is printed by the dmesg

Try putting an infinite loop inside a system call, the system just drops dead. As it goes, the linux kernel does not preempt itself.

<1> means that we are giving that message the highest priority Create a folder name ‘test’ in the root of linux source directory and save this file as strcpy.c in that directory . Create a makefile in that directory containing the line Obj-y:=strcpy.o The Edits The files to be edited are 1 . /usr/src/linux-2.6.32.5/arch/x86/kernel/syscall_table_32.S Append the line  .long sys_strcpy to the file(Replace sys_strcpy with whatever name you want) 2. /usr/src/linux-2.6.32.5/arch/x86/include/asm/unistd_32.h This file contains the unique number associated with each system call. We can see the names of all the system calls and the number associated with each. After the last system call-number pair (around line 345), add a line
#define __NR_strcpy  338  (if 337 was the number associated with the last system call).
Then replace NR_syscalls directive denoting the total number of system calls by the previous number incremented by 1 ie the new value id
#define NR_syscalls 339 Note down the number 338, we need it later. 3. /usr/src/linux-2.6.32.5/include/linux/syscalls.h This file contains the prototypes of system calls. Here we append to the file the prototype of our file.
ie. We add  the line
asmlinkage  long sys_strcpy(char *dest,char *src);
4. Makefile
Open makefile and find the area where core-y is defined and add the folder test to the end of that line as shown below
Advertisements

Posted in Kernel | Tagged: , , | 26 Comments »