I have shifted gears from finishing my cache coherency problems, to working on a fundamental part of the project: syscall redirection. Originally this was semi-finished, since we were using a stock 2.4 kernel. Now is has become a big obstacle now that we are working on a 2.6 kernel. After doing some research, I am unable at this time to fully implement syscall redirection (syscall hijacking) for the 2.6 kernel. The basic algorithm looks like this (for the 2.6 kernel):
main:
get sys call table address
save old address of sys call function
insert new address of new sys call function
new sys call function
print message
call old sys call function
I can make the switch of addresses and get into the new sys call function, but from there, I lose control. I cannot use the keyboard anymore and I am force to do a hard reboot.
The code I am using looks like this:
// thanks to: http://www.gnome.org/~lcolitti/gnome-startup/linux-iolog/readlog.c #include < linux/init.h > #include < linux/module.h > #include < linux/kernel.h > #include < linux/syscalls.h > #include < asm/unistd.h > MODULE_LICENSE("GPL"); unsigned long **sys_call_table; ssize_t (*orig_read)(int f, const void *buf, size_t n); // Stolen from scprint.c // http://downloads.securityfocus.com/downloads/scprint.tar.gz unsigned long **find_sys_call_table(void) { unsigned long **sctable; unsigned long ptr; extern int loops_per_jiffy; sctable = NULL; for (ptr = (unsigned long)&loops_per_jiffy; ptr < (unsigned long)&boot_cpu_data; ptr += sizeof(void *)) { unsigned long *p = (unsigned long *)ptr; if (p[__NR_close] == (unsigned long) sys_close) { sctable = (unsigned long **)p; return &sctable[0]; } } return NULL; } ssize_t scr(int fd, const void *buf, size_t n) { printk(KERN_INFO "*** scr: Interception!\n"); return orig_read(fd, buf, n); } static int __init scr_init(void) { sys_call_table = find_sys_call_table(); printk(KERN_INFO "*** scr started * sys call table %p\n", sys_call_table); orig_read = (void *) (sys_call_table[__NR_read]); sys_call_table[__NR_read] = (void *) scr; return 0; } static void __exit scr_exit(void) { printk(KERN_INFO "*** scr unloaded\n"); sys_call_table[__NR_read] = (void *) orig_read; } module_init(scr_init); module_exit(scr_exit);
This is very cut & dry code, but it doesn't work.