You are on page 1of 10

ADDING NEW SYSTEM CALL

Download and extract Kernel source


wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.16.tar.xz
sudo tar -xvf linux-3.16.tar.xz -C/usr/src/
cd /usr/src/linux-3.16/
Define a new system call sys_listit(char *path,char type)
mkdir listit
cd listit
gedit listit.c
add the code
gedit Makefile, add the following line to it: obj-y := listit.o

source code 1

Add the listit directory to the kernels Makefile


gedit Makefile inside linux 3.16
goto line number 842 core-y += kernel/ mm/ fs/ ipc/ security/
crypto/ block/
add listit/ at the end of it.

Add the new system call (sys_listit() ) into the system call table
(syscall_32.tbl file)
cd arch/x86/syscalls
gedit syscall_32.tbl
add the following line in the end of the file :- 355

i386 listit

sys_listit

Add the new system call(sys_listit() ) in the system call header file.
cd

include/linux/

gedit syscalls.h
add the line : asmlinkage long sys_listit(char *path,char type);

Compile this kernel on your system.


Download and install some prerequisite.
sudo apt-get install gcc
sudo apt-get install libncurses5-dev

update and upgrade sudo apt-get update && sudo apt-get upgrad e
cd /usr/src/linux-3.16/
To configure your kernel use the following command: sudo make defconfig
to compile the kernel :
make

To install /update the kernel.


sudo make modules_install install
shutdown -r now

Test Your system call


source code 2

Making Patch
cd /usr/src/linux-3.16/
make mrproper
make clean
cd /usr/src
diff -Nur oldpath newpath > patchname
diff -Nur /home/faiz/Downloads/linux-3.16 /usr/src/linux-3.16 >

patch2

Isuues
fix the syntax errors of syscall.c by writing appropriate function in

kernel level and include the corresponding header files also.


kernel compiled but userlevel process is Killed due to less memory or

infinite loop.,
each directory is taking 5MB of size, if you have more folders in
your testing directory, critical for the system. Process may get killed.
userlevel process returns -1 , fix : select the right kernel from the

grub and run the userlevel program again

System restarted ,error message : Disk drive /tmp is not ready

fix by typing f, or delete the /tmp folder and then create a new /tmp

Source_code#1

sys_listit()

#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <asm/uaccess.h>
#include <linux/syscalls.h>
#include <linux/linkage.h>
#include <linux/dirent.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/types.h>
#include <linux/time.h>
#include <linux/slab.h>

long list(char *path,char t);

struct stat statbuf;


int status;

struct linux_dirent {
long

d_ino; //Inode number

off_t

d_off; //Offset to next linux_dirent

unsigned shortd_reclen;

//Length of this linux_dirent

char

//Filename (null-terminated)

d_name[];

/*
char

pad;

//Zero padding byte

char d_type; //File type (only since Linux


//2.4.6); offset is (d_reclen - 1)
*/
};
#define BUF_SIZE 1024*1024*5

/*type
d- directory
f- regular file
s- symbolic link
a- all types.

*/

asmlinkage long sys_listit(char *path, char type)


{
unsigned long start=jiffies, end;

printk("\n\n filepath\n i-node file-type size permission-mode owner last-access-time


modified-time\n");
printk("------------------------------------------------------------------------------------------------\n");
list(path,type);

end=jiffies;

printk(KERN_INFO "\n Total Time Taken = %u usecs.\n", jiffies_to_usecs(end - start));

return 0;
}

long list(char *path,char t)


{
char *type="regular";

mm_segment_t fs;
int fd;
char locBuf[100];
char buf[BUF_SIZE];
struct linux_dirent *d;
int bpos;
char d_type;
int nread;
fs=get_fs();

sprintf(locBuf, path);
set_fs(get_ds());

if((fd = sys_openat(AT_FDCWD, locBuf, O_RDONLY|O_NONBLOCK|O_DIRECTORY|


O_CLOEXEC, S_IRWXU)) < 0)
{
//printk(KERN_INFO "Cannot open location :%s\n", path);
return 1;
}
else
{

nread = sys_getdents(fd, buf, BUF_SIZE);


size_t arglen = strlen(path);

for(bpos=0;bpos<nread;)
{
d=(struct linux_dirent *) (buf+bpos);
d_type = *(buf + bpos + d->d_reclen - 1);

/* + 2 because of the '/' and the terminating 0 */


char *full = kmalloc(arglen + strlen(d->d_name) + 2,GFP_KERNEL);
if (full == NULL) { /* deal with error and exit */ }
sprintf(full, "%s/%s", path, d->d_name);
/* use fullpath */

status = sys_newstat(full, &statbuf);

if(d_type==DT_REG && t=='f'){

type="regular";
printk("%s\n",full);
printk("%8ld %-10s %10ld ", d->d_ino,type,statbuf.st_size);
printk("%o ",statbuf.st_mode & (S_IRWXU | S_IRWXG |
S_IRWXO));
printk("%5u ",statbuf.st_uid);

struct tm broken;
time_to_tm(statbuf.st_atime, 0, &broken);
printk(" %2d:%2d:%2d ", broken.tm_hour,
broken.tm_min,broken.tm_sec);

struct tm broken1;
time_to_tm(statbuf.st_mtime, 0, &broken1);
printk(" %2d:%2d:%2d \n", broken1.tm_hour,

broken1.tm_min,broken1.tm_sec);

}
else if(d_type==DT_DIR && t=='d'){

type="directory";

printk("%s\n",full);
printk("%8ld %-10s %10ld ", d->d_ino,type,statbuf.st_size);
printk("%o ",statbuf.st_mode & (S_IRWXU | S_IRWXG |
S_IRWXO));
printk("%5u ",statbuf.st_uid);

struct tm broken;
time_to_tm(statbuf.st_atime, 0, &broken);
printk(" %2d:%2d:%2d ", broken.tm_hour,
broken.tm_min,broken.tm_sec);

struct tm broken1;
time_to_tm(statbuf.st_mtime, 0, &broken1);
printk(" %2d:%2d:%2d \n", broken1.tm_hour,
broken1.tm_min,broken1.tm_sec);

}
else if(d_type==DT_LNK && t=='s'){

type="link";

printk("%s\n",full);
printk("%8ld %-10s %10ld ", d->d_ino,type,statbuf.st_size);
printk("%o ",statbuf.st_mode & (S_IRWXU | S_IRWXG |

S_IRWXO));
printk("%5u ",statbuf.st_uid);

struct tm broken;
time_to_tm(statbuf.st_atime, 0, &broken);
printk(" %2d:%2d:%2d ", broken.tm_hour,
broken.tm_min,broken.tm_sec);

struct tm broken1;
time_to_tm(statbuf.st_mtime, 0, &broken1);
printk(" %2d:%2d:%2d \n", broken1.tm_hour,
broken1.tm_min,broken1.tm_sec);
}
else if(t=='a'){

if(d_type==DT_REG)
type="regular";
else if(d_type==DT_DIR)
type="directory";
else if(d_type==DT_LNK)
type="link";
else
type="other";

printk("%s\n",full);
printk("%8ld %-10s %10ld ", d->d_ino,type,statbuf.st_size);
printk("%o ",statbuf.st_mode & (S_IRWXU | S_IRWXG |
S_IRWXO));
printk("%5u ",statbuf.st_uid);

struct tm broken;

time_to_tm(statbuf.st_atime, 0, &broken);
printk(" %2d:%2d:%2d ", broken.tm_hour,
broken.tm_min,broken.tm_sec);

struct tm broken1;
time_to_tm(statbuf.st_mtime, 0, &broken1);
printk(" %2d:%2d:%2d \n", broken1.tm_hour,
broken1.tm_min,broken1.tm_sec);
}

if(d_type==DT_DIR && d->d_name !=NULL){


if(strcmp(d->d_name,".")!=0 && strcmp(d->d_name,"..")!=0){
list(full,t);
}
}
bpos += d->d_reclen;
kfree(full);
}
}
sys_close(fd);
set_fs(fs);
return 0;

Source_code#2

test.c
#include <stdio.h>

#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>

/*type
d- directory
f- regular file
s- symbolic link
a- all types.

*/

int main()
{
int x=4;
char *loc= "/home/faiz/Downloads";
char type='f';
printf("\n Enter :\n");
printf("\n type :\t");
scanf("%c",&type);
printf("%ld",syscall(355,loc,type));
return 0;
}

You might also like