10

I have been trying to intercept the system call at the kernel level. I got the basic idea from this question . The system call I was trying to intercept was the fork(). So I found out the address of the sys_fork() from System.map and it turned out to be 0xc1010e0c.Now I wrote the module as below.

#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/unistd.h>
#include<linux/semaphore.h>
#include<asm/cacheflush.h>
MODULE_LICENSE("GPL");
void **sys_call_table;
asmlinkage int (*original_call)(struct pt_regs);
asmlinkage int our_call(struct pt_regs regs)
{
    printk("Intercepted sys_fork");
    return original_call(regs);
} 
static int __init p_entry(void)
{
    printk(KERN_ALERT "Module Intercept inserted");
    sys_call_table=(void *)0xc1010e0c;
    original_call=sys_call_table[__NR_open];
    set_memory_rw((long unsigned int)sys_call_table,1);
    sys_call_table[__NR_open]=our_call;
    return 0;
}
static void __exit p_exit(void)
{
    sys_call_table[__NR_open]=original_call;
    set_memory_ro((long unsigned int)sys_call_table,1);
    printk(KERN_ALERT "Module Intercept removed");
}
module_init(p_entry);
module_exit(p_exit);

However , after compiling the module and when I tried to insert it to the kernel, I got the following from the dmesg output. enter image description here enter image description here

Of course its not intercepting the system call.Can you help me figure out the problem? I am using 3.2.0-4-686 version of Linux kernel.

Community
  • 1
  • 1
PaulDaviesC
  • 1,161
  • 3
  • 16
  • 31

3 Answers3

8

http://lxr.linux.no/linux+*/arch/x86/mm/pageattr.c#L874 says

            if (*addr & ~PAGE_MASK) {
                    *addr &= PAGE_MASK;
                    /*
                     * People should not be passing in unaligned addresses:
                     */
                    WARN_ON_ONCE(1);
            }

So the warning is because your sys_call_table variable is not page-aligned.

It should be said that patching the system call table is officially discouraged by the kernel maintainers, and they've put some deliberate roadblocks in your way -- you've probably already noticed that you can't access the real sys_call_table symbol, and the write protection is also deliberate. If you can possibly find another way to do what you want, then you should. Depending on your larger goal, you might be able to accomplish it using ptrace and no kernel module at all. The trace_sched_process_fork hook may also be useful.

zwol
  • 135,547
  • 38
  • 252
  • 361
2
original_call=sys_call_table[__NR_open];
....
sys_call_table[__NR_open]=our_call;

If you're intercepting fork, the entry for open is not what you want to change. And instead of the address of the sys_fork() from System.map, you should have used the address of sys_call_table.

Anton Kovalenko
  • 20,999
  • 2
  • 37
  • 69
  • Yep. But (just edited the answer) you should use the address of sys_call_table to initialize your sys_call_table pointer, not the original address of sys_fork. – Anton Kovalenko Jan 19 '13 at 15:08
  • Of course I made a mistake by using __NR_open instead of __NR_fork. But the problem doesn't seem to end there. Now I am unsure about validity of applying set_memeory_rw() to sys_call_table. That has to be investigated further. Any inputs? – PaulDaviesC Jan 20 '13 at 03:59
0

It is not clear if you solved your problem, but depending on how you test your module glib don't use sys_fork anymore, but use sys_clone instead.

tfjmp
  • 1
  • 2