/* mod-syscall-retparm.c * System calls with printk, but this time replace three * system calls, no parms and results, no parms with results, * and parms with results. * * Derived from the no-parameter or result hello-1 example in the * Linux Kernel Module Programmer's Guide for 2.4 Kernel. * * We'll used an existing syscall entry (futex) and replace it * * Include file locations * is /usr/src/linux/include/linux * is /usr/src/linux/include/asm * is /usr/include/sys * * Source file locations * sys_call_table[] /usr/src/linux/arch/i386/kernel/entry.S */ /* kernel module programming */ #ifndef MODULE #define MODULE #endif #ifndef LINUX #define LINUX #endif #ifndef __KERNEL__ #define __KERNEL__ #endif #define MAX_BUF 80 #include /* needed by all modules */ #include /* for KERN_ALERT */ #include /* for __NR_futex & other system call numbers */ /* The kernel will fill in the call table at dynamic load (insmod) */ extern void *sys_call_table[]; /* prototypes */ asmlinkage void my_syscall(void); asmlinkage int my_syscall_ret(void); asmlinkage int my_syscall_parm(char *msg); int init_module(void); void cleanup_module(void); /* My module system call */ asmlinkage void my_syscall(void) { printk(KERN_ALERT "my_syscall: entering.\n"); printk(KERN_ALERT "my_syscall: leaving.\n"); } /* My module system call to return a value * The value must be on the stack. If the stack * value is a reference to memory, then it * won't work. */ asmlinkage int my_syscall_ret(void) { printk(KERN_ALERT "my_syscall_ret: entering.\n"); printk(KERN_ALERT "my_syscall_ret: leaving.\n"); return 7; } /* My module system call to pass a parameter and return a value */ asmlinkage int my_syscall_parm(char *msg) { printk(KERN_ALERT "my_syscall_parm: entering.\n"); printk(KERN_ALERT "message from user: %s\n", msg); printk(KERN_ALERT "my_syscall_parm: leaving.\n"); return 11; } /* Original system call for NR_futex (240) in sys.c of src/linux/kernel/sys.c * The original call is sys_ni_syscall and returns an error number. * Same for the other two unused system calls 241 & 242 here. */ asmlinkage long (*original_call_240) (void); /* Original system call for NR_sched_setaffinity sys.c of src/linux/kernel */ asmlinkage long (*original_call_241) (void); /* Original system call for NR_sched_getaffinity sys.c of src/linux/kernel */ asmlinkage long (*original_call_242) (void); /* Initialize the module at insmod - insert the new system calls */ int init_module(void) { printk(KERN_ALERT "syscall-retparm module loaded\n"); /* save the original syscall entry and insert our own entry */ original_call_240 = sys_call_table[__NR_futex]; original_call_241 = sys_call_table[__NR_sched_setaffinity]; original_call_242 = sys_call_table[__NR_sched_getaffinity]; sys_call_table[__NR_futex] = my_syscall; sys_call_table[__NR_sched_setaffinity] = my_syscall_ret; sys_call_table[__NR_sched_getaffinity] = my_syscall_parm; /* A non-zero return means init_module failed; module can't be loaded */ return 0; } /* Restore the preious system call at rmmod. * Check to see if someone else tried to replace our * system calls while we were loaded. */ void cleanup_module(void) { if (sys_call_table[__NR_futex] != my_syscall || sys_call_table[__NR_sched_setaffinity] != my_syscall_ret || sys_call_table[__NR_sched_getaffinity] != my_syscall_parm) { printk(KERN_ALERT "syscall module entry has been corrupted\n"); } /* restore the original syscall entry */ sys_call_table[__NR_futex] = original_call_240; sys_call_table[__NR_sched_setaffinity] = original_call_241; sys_call_table[__NR_sched_getaffinity] = original_call_242; printk(KERN_ALERT "syscall-retparm module unloaded\n"); } MODULE_LICENSE("GPL");