I am working on a project in which i have hooked the system open call. When a user attempts to open a file i want sys_open to block the action if the current task (pid or tgid that "black listed" ) has potential to leak the file out of the host.
Any ways, the hooking itself worked fine on sys_read and sys_write (I have some printk inside the fake function as an indicator).
but, when i try the hooking on the sys_open function, nothing is printed out - means that the override not succeeded. I printed out the address of the sys call before and after the override so this might not be the issue.
I am confused about what can cause that uneven behavior when hooking different functions.
will be glad for some input here. thanks !
dmesg output examples:
when hooked write -
...
[ 2989.500485] in my write ...
[ 2989.500585] in my write ...
when hooked open, noting printed, but here some "debug" output -
[ 890.709696] address found 00000000103d42f6
[ 890.709697] Address before - 0000000006d29c3a
[ 890.709698] Address after - 00000000a5117c6a
[ 948.533339] BYE !!!
using lubuntu vm (kernel v 4.15.0.20).
here is the source code:
#include <linux/init.h> // Macros used to mark up functions e.g., __init __exit #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/types.h> #include <linux/syscalls.h> #include <linux/sched.h> #include <asm/uaccess.h> #include <asm/unistd.h> #include <asm/page.h> #include <linux/kallsyms.h> #include <linux/semaphore.h> #include <asm/cacheflush.h> #include <linux/set_memory.h> #include <linux/cred.h> #include <linux/user.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("ABC"); MODULE_VERSION("0.1"); asmlinkage long (*original_call)( char __user *filename, int flags, umode_t mode); // for read or write: (unsigned int fd, char __user *buf, size_t count); asmlinkage long my_sys_READ(unsigned int fd, char __user *buf, size_t count); asmlinkage long my_sys_WRITE(unsigned int fd, char __user *buf, size_t count); asmlinkage long my_sys_OPEN( char __user *filename, int flags, umode_t mode); unsigned long* find_sys_call_table(void); void set_page_rw( unsigned long addr); void set_page_ro( unsigned long addr); const struct cred *_cred = NULL ; struct user_struct *user =NULL ; unsigned long* sys_call_table = NULL; void set_page_rw(unsigned long addr) { unsigned int level; pte_t *pte = lookup_address(addr, &level); if (pte->pte &~ _PAGE_RW) pte->pte |= _PAGE_RW; } void set_page_ro( unsigned long addr) { unsigned int level; pte_t *pte = lookup_address(addr, &level); pte->pte = pte->pte &~_PAGE_RW; } /* asmlinkage long my_sys_READ(unsigned int fd, char __user *buf, size_t count) { //_cred = current_cred(); user = get_current_user(); if( (int)(*user).uid.val == uid ) { printk(KERN_ALERT"in my read ... hacked !"); return original_call(fd, buf, count); } printk(KERN_ALERT"in my read ... hacked !"); return original_call(fd, buf, count); } asmlinkage long my_sys_WRITE(unsigned int fd, char __user *buf, size_t count) { //_cred = current_cred(); user = get_current_user(); if( (int)(*user).uid.val == uid ) { printk(KERN_ALERT"in my write ... hacked !"); return original_call(fd, buf, count); } printk(KERN_ALERT"in my write ... hacked !"); return original_call(fd, buf, count); } */ asmlinkage long my_sys_OPEN( char __user *filename, int flags, umode_t mode) { printk(KERN_ALERT"in my open ... hacked !"); return original_call(filename, flags, mode); } unsigned long* find_sys_call_table(void) { return (unsigned long *)kallsyms_lookup_name("sys_call_table"); } int init_module() { printk(KERN_ALERT "I'm dangerous. I hope you did a "); printk(KERN_ALERT "sync before you insmod'ed me.\n"); sys_call_table = find_sys_call_table(); printk(KERN_INFO"address found %p \n",sys_call_table); original_call = (void *)sys_call_table[__NR_open]; set_page_rw((unsigned long)sys_call_table); printk(KERN_INFO" Address before - %p", (void *)sys_call_table[__NR_open]); sys_call_table[__NR_open] = (unsigned long)my_sys_OPEN; printk(KERN_INFO" Address after - %p", (void *)sys_call_table[__NR_open]); return 0; } /* * Cleanup − unregister the appropriate file from /proc */ void cleanup_module() { /* * Return the system call back to normal */ if (sys_call_table[__NR_open] != (unsigned long)my_sys_OPEN) { printk(KERN_ALERT "Somebody else also played with the "); printk(KERN_ALERT "open system call\n"); } printk(KERN_ALERT "BYE !!!\n"); sys_call_table[__NR_open] = (unsigned long)original_call; }
straceon your use space program that you use for testing to see which system call it calls ?(e.g. it might call openat() instead of open())