2013-09-20 4 views
1

Итак, я пытаюсь добавить syscall в свою Linux из модуля ядра. Вот код модуля.Как добавить системный вызов из модуля ядра?

asmlinkage int my_syscall() { 
    printk(KERN_INFO "AWESOME!\n"); 
    return 0; 
} 

int load() { 
    unsigned long ** addr; 
    unsigned long int i = START; 

    printk(KERN_INFO "IN\n"); 

    while (i < END) { 
     addr = (unsigned long **)i; 
     if (addr[__NR_close] == (unsigned long *)sys_close) { 
      break; 
     } 
     i += sizeof(void *); 
    } 

    if (i != END) { 
     addr += __NR_vserver; 
     struct page * p = virt_to_page(addr); 
     unsigned long paddr = (unsigned long)page_address(p); 
     set_memory_rw(paddr, 15); 
     *addr = &my_syscall; 
     set_memory_ro(paddr, 15); 
    } 

    return 0; 
} 

void unload() { 
    printk(KERN_INFO "OUT\n"); 
} 

module_init(load); 
module_exit(unload); 

Так что я смотрю на sys_call_table и однажды я нашел его, я пытаюсь переопределить не реализованный системный вызов (vserver). Когда я insmod получившийся .ko, вот что dmesg говорит:

BUG: unable to handle kernel paging request at ffffffff81801bc0 

0xffffffff81801bc0 фактически адрес, где я tryng писать &my_syscall. Я не знаю точно, что я делаю неправильно, но я думаю, что страница памяти все еще может быть в режиме ro, когда я пытаюсь написать ...

ответ

-3

Похоже, что вы что-то пропустили во внедрении системы вызов. Просто взгляните на http://arvindsraj.wordpress.com/2012/10/05/adding-hello-world-system-call-to-linux/, в котором объясняется пошаговая процедура для реализации системного вызова и проверка того, правильно ли вы выполняли все шаги или нет.

+0

Это не о добавлении системного вызова * из модуля *. – duskwuff

0

То, что я не понимаю, следующая строка:

set_memory_rw(paddr, 15); 

Что должно произойти здесь?

Вы не можете изменить атрибуты физического адреса!

Может быть, следующий код является правильным:

set_memory_rw(addr, 15); 

(В этом случае вам не нужен физический адрес «paddr», ни на странице «р».)

В качестве альтернативы вы можете попробовать карту физический адрес второй раз в пространстве ядра.

Вы должны восстановить исходный указатель в функции «выгрузить()»!

0

Если 0xffffffff81801bc0 - это фактический адрес, который вы передали в set_memory_rw(), то это определенно неправильное значение. адрес должен быть округлен до границы PAGE_MASK, то есть начального адреса страницы, который обычно заканчивается на 4 нуля для 64-битной системы.

set_memory_rw() обрабатывает бит U/S таблиц страниц памяти. Но есть другой атрибут для процессора x86/amd64: бит WP (внутри cr0). Согласно руководству Intel, бит WP переопределяет атрибут таблицы страниц памяти, т. Е. Включение/отключение бита WP будет по-прежнему работать независимо от того, что память только для чтения или нет. Но тогда бит WP является per-cpu, поэтому тщательно синхронизируйте доступ к памяти, чтобы при изменении содержимого памяти другой процессор не читал его. (для вашего неиспользуемого номера системы безопасности это не должно быть проблемой).

http://vulnfactory.org/blog/2011/08/12/wp-safe-or-not/

Смежные вопросы