我一直试图在内核级拦截系统调用。我从这个question得到了基本的想法。我试图拦截的系统调用是 fork()。所以我从System.map中找到了 sys_fork()的地址,结果证明是0xc1010e0c。现在我编写了如下模块。
#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);
但是,在编译模块后,当我尝试将其插入内核时,我从dmesg输出中得到以下内容。
当然它不会拦截系统调用。你能帮我解决问题吗?我正在使用 3.2.0-4-686 版本的Linux内核。
答案 0 :(得分:7)
http://lxr.linux.no/linux+*/arch/x86/mm/pageattr.c#L874
说
if (*addr & ~PAGE_MASK) {
*addr &= PAGE_MASK;
/*
* People should not be passing in unaligned addresses:
*/
WARN_ON_ONCE(1);
}
所以警告是因为你的sys_call_table
变量没有页面对齐。
应该说内核维护人员正式不鼓励修补系统调用表,并且他们在你的方式中设置了一些故意的障碍 - 你可能已经注意到你无法访问真正的{{ 1}}符号,写保护也是故意的。如果你可以找到另一种方法来做你想做的事,那么你应该。根据您的更大目标,您可以使用ptrace
完成它,而根本不需要内核模块。 sys_call_table
钩子也可能有用。
答案 1 :(得分:2)
original_call=sys_call_table[__NR_open];
....
sys_call_table[__NR_open]=our_call;
如果您正在拦截fork
,则open
的条目不是您想要更改的内容。
而不是System.map中sys_fork()的地址,您应该使用sys_call_table
的地址。
答案 2 :(得分:0)
目前尚不清楚您是否解决了问题,但根据您测试模块的方式,glib不再使用sys_fork,而是使用sys_clone。