Перехват системного вызова

Я пытаюсь перехватить системный вызов на уровне ядра. Я получил основную идею из question. Системный вызов, который я пытался перехватить, был fork(). Поэтому я узнал адрес sys_fork() из System.map, и оказалось, что он равен 0xc1010e0c.Now. Я написал модуль, как показано ниже.

#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. enter image description hereenter image description here

Конечно, он не перехватывает системный вызов. Можете ли вы помочь мне разобраться в проблеме? Я использую 3.2.0-4-686 версию ядра Linux.

Ответ 1

original_call=sys_call_table[__NR_open];
....
sys_call_table[__NR_open]=our_call;

Если вы перехватываете fork, запись для open не является тем, что вы хотите изменить. И вместо адреса sys_fork() из System.map вы должны использовать адрес sys_call_table.

Ответ 2

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 не выровнена по странице.

Следует сказать, что исправление таблицы системных вызовов официально обескуражено сторонними разработчиками ядра, и они поставили некоторые преднамеренные препятствия на вашем пути - вы, вероятно, уже заметили, что не можете получить доступ к реальному sys_call_table, а защита записи также преднамеренно. Если вы можете найти другой способ сделать то, что хотите, тогда вам нужно. В зависимости от вашей более крупной цели вы можете выполнить ее с помощью ptrace и вообще не иметь модуля ядра. Ключ trace_sched_process_fork также может быть полезен.

Ответ 3

Неясно, решили ли вы свою проблему, но в зависимости от того, как вы тестируете glib модуля, больше не используйте sys_fork, но вместо этого используйте sys_clone.