c - Linux Kernel: System call hooking example -


i'm trying write simple test code demonstration of hooking system call table.

"sys_call_table" no longer exported in 2.6, i'm grabbing address system.map file, , can see correct (looking through memory @ address found, can see pointers system calls).

however, when try modify table, kernel gives "oops" "unable handle kernel paging request @ virtual address c061e4f4" , machine reboots.

this centos 5.4 running 2.6.18-164.10.1.el5. there sort of protection or have bug? know comes selinux, , i've tried putting in permissive mode, doesn't make difference

here's code:

#include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/unistd.h>  void **sys_call_table;  asmlinkage int (*original_call) (const char*, int, int);  asmlinkage int our_sys_open(const char* file, int flags, int mode) {    printk("a file opened\n");    return original_call(file, flags, mode); }  int init_module() {     // sys_call_table address in system.map     sys_call_table = (void*)0xc061e4e0;     original_call = sys_call_table[__nr_open];      // hook: crashes here     sys_call_table[__nr_open] = our_sys_open; }  void cleanup_module() {    // restore original call    sys_call_table[__nr_open] = original_call; } 

i found answer myself.

http://www.linuxforums.org/forum/linux-kernel/133982-cannot-modify-sys_call_table.html

the kernel changed @ point system call table read only.

cypherpunk:

even if late solution may interest others too: in entry.s file find: code:

.section .rodata,"a" #include "syscall_table_32.s" 

sys_call_table -> readonly have compile kernel new if want "hack" around sys_call_table...

the link has example of changing memory writable.

nasekomoe:

hi everybody. replies. solved problem long ago modifying access memory pages. have implemented 2 functions upper level code:

#include <asm/cacheflush.h> #ifdef kern_2_6_24 #include <asm/semaphore.h> int set_page_rw(long unsigned int _addr) {     struct page *pg;     pgprot_t prot;     pg = virt_to_page(_addr);     prot.pgprot = vm_read | vm_write;     return change_page_attr(pg, 1, prot); }  int set_page_ro(long unsigned int _addr) {     struct page *pg;     pgprot_t prot;     pg = virt_to_page(_addr);     prot.pgprot = vm_read;     return change_page_attr(pg, 1, prot); }  #else #include <linux/semaphore.h> int set_page_rw(long unsigned int _addr) {     return set_memory_rw(_addr, 1); }  int set_page_ro(long unsigned int _addr) {     return set_memory_ro(_addr, 1); }  #endif // kern_2_6_24 

here's modified version of original code works me.

#include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/unistd.h> #include <asm/semaphore.h> #include <asm/cacheflush.h>  void **sys_call_table;  asmlinkage int (*original_call) (const char*, int, int);  asmlinkage int our_sys_open(const char* file, int flags, int mode) {    printk("a file opened\n");    return original_call(file, flags, mode); }  int set_page_rw(long unsigned int _addr) {    struct page *pg;    pgprot_t prot;    pg = virt_to_page(_addr);    prot.pgprot = vm_read | vm_write;    return change_page_attr(pg, 1, prot); }  int init_module() {     // sys_call_table address in system.map     sys_call_table = (void*)0xc061e4e0;     original_call = sys_call_table[__nr_open];      set_page_rw(sys_call_table);     sys_call_table[__nr_open] = our_sys_open; }  void cleanup_module() {    // restore original call    sys_call_table[__nr_open] = original_call; } 

Comments

Popular posts from this blog

ruby - When to use an ORM (Sequel, Datamapper, AR, etc.) vs. pure SQL for querying -

php - PHPDoc: @return void necessary? -

c++ - Convert big endian to little endian when reading from a binary file -