Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > Перехват вызовов в ядре


Автор: RankoR 24.9.2010, 10:23
Есть модуль ядра (нагугленный), перехватывающий вызов open()

Код

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/unistd.h>
#include <linux/semaphore.h>
#include <asm/cacheflush.h>

MODULE_LICENSE("Dual BSD/GPL");

typedef long unsigned int uli;

static void **sys_call_table;

asmlinkage int (*original_call) (const char*, int, int);

asmlinkage int our_sys_open(const char* file, int flags, int mode)
{
    if ( ! strcmp(file, "1.txt") )
        printk("A file was opened\n");
    return original_call(file, flags, mode);
}

int set_page_rw(uli _addr, bool write)
{
   struct page *pg;
   pgprot_t prot;
   pg = virt_to_page(_addr);
   prot.pgprot = ( (write) ? VM_READ | VM_WRITE : VM_READ );
   return set_pages_uc(pg, 1);
}

static int hooks_init()
{
    // sys_call_table address in System.map
    sys_call_table = (void *) 0xc05f9260;
    original_call = sys_call_table[__NR_open];

    set_page_rw((uli) sys_call_table, true);
    sys_call_table[__NR_open] = our_sys_open;
    return 0;
}

static void hooks_exit()
{
    // Restore the original call
    sys_call_table[__NR_open] = original_call;
    set_page_rw((uli) sys_call_table, false);
}

module_init(hooks_init);
module_exit(hooks_exit);


Модуль вылетает при попытке запуска с сообщением "Убито". Опытным путем выявлено, что это случается на строчке
sys_call_table[__NR_open] = our_sys_open;

Вот что показывает dmesg
Код

[ 7170.506399] Oops: 0003 [#1] SMP 
[ 7170.506408] last sysfs file: /sys/devices/pci0000:00/0000:00:0b.0/host1/target1:0:0/1:0:0:0/block/sda/uevent
[ 7170.506420] Modules linked in: hooksmod(+) binfmt_misc vboxnetadp vboxnetflt vboxdrv parport_pc ppdev snd_hda_codec_nvhdmi snd_hda_codec_realtek nvidia(P) snd_hda_intel snd_hda_codec snd_hwdep snd_pcm snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq snd_timer snd_seq_device snd soundcore lp i2c_nforce2 joydev asus_atk0110 agpgart psmouse serio_raw snd_page_alloc shpchp parport usbhid hid r8169 ahci libahci mii [last unloaded: hooksmod]
[ 7170.506509] 
[ 7170.506520] Pid: 13015, comm: insmod Tainted: P            2.6.35-22-generic-pae #33-Ubuntu AT3IONT-I/System Product Name
[ 7170.506530] EIP: 0060:[<f8523080>] EFLAGS: 00210286 CPU: 2
[ 7170.506541] EIP is at hooks_init+0x30/0x40 [hooksmod]
[ 7170.506549] EAX: c05f9260 EBX: 08219018 ECX: c0807ffc EDX: 00000000
[ 7170.506557] ESI: f8523140 EDI: 00000000 EBP: c880df5c ESP: c880df5c
[ 7170.506565]  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 7170.506574] Process insmod (pid: 13015, ti=c880c000 task=f22f0cb0 task.ti=c880c000)
[ 7170.506581] Stack:
[ 7170.506585]  c880df88 c0103042 f8523140 c080b260 08219018 f8523140 00004000 f8523050
[ 7170.506605] <0> 08219018 f8523140 00004000 c880dfac c0188f1b 00000003 c880dfac c02208e5
[ 7170.506626] <0> f22d6540 08219018 08219018 08219cde c880c000 c010939f 08219018 00000cc6
[ 7170.506649] Call Trace:
[ 7170.506666]  [<c0103042>] ? do_one_initcall+0x32/0x1a0
[ 7170.506680]  [<f8523050>] ? hooks_init+0x0/0x40 [hooksmod]
[ 7170.506695]  [<c0188f1b>] ? sys_init_module+0x9b/0x1e0
[ 7170.506708]  [<c02208e5>] ? sys_close+0x75/0xc0
[ 7170.506722]  [<c010939f>] ? sysenter_do_call+0x12/0x28
[ 7170.506730] Code: 44 00 00 a1 74 92 5f c0 ba 01 00 00 00 c7 05 b8 32 52 f8 60 92 5f c0 a3 b4 32 52 f8 b8 60 92 5f c0 e8 85 ff ff ff a1 b8 32 52 f8 <c7> 40 14 90 30 52 f8 31 c0 5d c3 90 8d 74 26 00 55 89 e5 53 83 
[ 7170.506841] EIP: [<f8523080>] hooks_init+0x30/0x40 [hooksmod] SS:ESP 0068:c880df5c
[ 7170.506860] CR2: 00000000c05f9274
[ 7170.506870] ---[ end trace 60e6ad44554d3423 ]---



Адрес из System.map верный (точнее, из /boot/System.map-2.6.35-22-generic-pae), страница памяти (по идее) должна быть writable. Почему такое может быть?

Автор: wlad110 24.9.2010, 17:45
Цитата

страница памяти (по идее) должна быть writable

Т.е. вы собирали ядро с writeable секцией ?
А то насколько знаю по дефолту запись запрещена.
Код

// entry_32.S
.section .rodata,"a"
#include "syscall_table_32.S"



Автор: RankoR 24.9.2010, 20:09
Цитата(wlad110 @  24.9.2010,  17:45 Найти цитируемый пост)
Т.е. вы собирали ядро с writeable секцией ?
А то насколько знаю по дефолту запись запрещена.

В том-то и дело, что нет - для этого есть функция, ставящая странице памяти атрибут R+W 
Код

int set_page_rw(uli _addr, bool write)
{
   struct page *pg;
   pgprot_t prot;
   pg = virt_to_page(_addr);
   prot.pgprot = ( (write) ? VM_READ | VM_WRITE : VM_READ );
   return set_pages_uc(pg, 1);
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)