For educational purposes, I want to implement a system call in Debian Wheezy. I wish to implement it on the kernel that comes in the linux-image-3.2.0--rt-amd64 package. Here is an overview of what I have tried:
To get the kernel source:
apt-get source linux-image-3.2.0-4-rt-amd64
From that, I get the following files/directories the directory I executed in:
linux_3.2.41.orig.tar.xz
linux_3.2.41-2+deb7u2.dsc
linux_3.2.41-2+deb7u2.debian.tar.xz
as well as:
linux_3.2.41
which contains the source code for the kernel.
Then, to make the necessary changes in order to add the system call, I basically followed this page: How to write system calls on debian/ubuntu
The following is a condensed version of the instructions given there modified to reflect the changes I made.
+File 1: linux-x.x.x/vpart_syscalls/vpart_syscalls.c
#include <linux/linkage.h>
#include <linux/kernel.h>
asmlinkage long insert_partition(char*dest, const char* src)
{
printk("<--- the syscall has been called!");
return 0;
}
File 2: linux-x.x.x/vpart_syscalls/Makefile. Create a Makefile within the same test directory you created above and put this line in it:
obj-y := vpart_syscalls.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 insert_partition
File 4: linux-x.x.x/arch/x86/include/asm/unistd_32.h
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_insert_partition 349
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 350
- File 5: linux-x.x.x/include/linux/syscalls.h
Append to the file the prototype of our function.
asmlinkage long insert_partition(int lenTicks, int vpid);
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/ vpart_syscalls/
I then proceeded to build the kernel in a different fashion than is described there:
make localmodconfig
make menuconfig (making no changes)
make-kpkg clean
fakeroot make-kpkg --initrd --append-to-version=+tm kernel_image kernel_headers
cd ..
dpkg -i linux-image-3.8.*
dpkg -i linux-headers-3.8.*
The kernel that is installed boots fine. I made the following c program to test the syscall:
#include <stdio.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
int main(){
printk("Calling the new syscall!\n");
int ret = 100;
ret = syscall(349, 1, 2);
printf("call return value: %i\n", ret);
return 0;
}
When I compile and run this program, I get a return value of -1. I check the messages using dmesg and there is no evidence of my printk being called..
If anyone knows where my problem is I would be really really happy! I should say I am not too experienced at changing and building the kernel, but I have learned a lot about it. I read Robert Loves book - linux kernel development and several guides on the webs.
uname -a
. Also, you can check your test withfile -k ./test_name
(to check 32/64 bit mode of the program) andstrace ./test_name
to see if the syscall called and what were arguments and the return value (strace should reportsyscall_349
for you syscall). - osgx