Home > database >  How to correctly intercept system calls in the Linux kernel 5.*?
How to correctly intercept system calls in the Linux kernel 5.*?

Time:04-05

There was a need to write a kernel module, with a hook for exec. I found a way with sys_calls_table and lsm. As I understand it, sys_calls_table is more of a hack than a correct solution, and I did not find normal examples for lsm.

How to correctly intercept a system call in modern kernel versions? I will be very happy with examples.

CodePudding user response:

There is no correct way to do this.

LSM (Linux Security Modules) doesn't support system calls interception, with LSMs you need the implemented some of the functions listed at lsm_hooks_defs.h.

There are two alternatives ways to intercept system calls which I'm aware of:

  1. Hook the sys_call_table which can be obtained, and overwrite the pointers with your new function:

    unsigned long *sys_call_table_ptr = kallsyms_lookup_name("sys_call_table");
    unsigned long cr0 = read_cr0();
    write_cr0(cr0 & ~x86_CR0_WP);
    sys_call_table_ptr[__NR_getpid] = new_getpid;
    write_cr0(cr0);
    
  2. Using kprobe: Syscall functions name expands with the prefix __do_sys_ (see __SYSCALL_DEFINEx). For example, kprobe on __do_sys_finit_module (or any other syscall you want) as follow:

    static struct kprobe kp = {
        .symbol_name    = "__do_sys_finit_module",
    };
    
    static int handler_pre(struct kprobe *p, struct pt_regs *regs) {
        // do your logic
        // obtain function arguments using register (calling convetion)
    }
    
    static int __init kprobe_init(void)
    {
        kp.pre_handler = handler_pre;
        ret = register_kprobe(&kp);
        if (ret < 0) {
            printk(KERN_INFO "register_kprobe failed, returned %d\n", ret);
            return ret;
        }
        printk(KERN_INFO "Planted kprobe at %p\n", kp.addr);
        return 0;
    }
    
    static void __exit kprobe_exit(void)
    {
        unregister_kprobe(&kp);
        printk(KERN_INFO "kprobe at %p unregistered\n", kp.addr);
    }
    
  • Related