0

В моем модульном модуле Linux 3.16 в какой-то момент я хочу перейти к процедуре обработки ошибок, например. do_invalid_op [Linux codeline]. Путем прямого вызова do_invalid_op в модуле ядра он немедленно разрушил всю систему Linux, даже без следа в /var/log/kern.log (для меня отладки). Например,Обработка исключений в модуле ядра

void module_begin(){ 
    ... 
    if(error_found){ 
     do_invalid_op(reg, error_code); //expected to return control to user space without running "a=1" line. 
    } 
    int a = 1; 
    ... 
} 

module_init(module_begin()); 

Мой общий вопрос заключается в том, чтобы преобразовать код обработки ошибок (обработчик прерывания) в модуле ядра?

Обновление 1: Код примера обновлен, чтобы отразить то, что я намерен выполнять модулю; один раз a error_found, выполнение ядра должно прыгать куда-то (например, пользовательское пространство), не запуская остальную часть кода инициализации модуля.

Update 2: Трассировка информации о аварии, надеюсь, что это полезно

Entering the yyy! 
Meaning of life: 41 
Value of tcs: 0x19e5010 
00400000-00401000 r-xp 00000000 08:01 304369        /home/tom/workspace/coding/xxx-emulator-v2/TR/client/bin/a.out 
00601000-00602000 r--p 00001000 08:01 304369        /home/tom/workspace/coding/xxx-emulator-v2/TR/client/bin/a.out 
00602000-00603000 rw-p 00002000 08:01 304369        /home/tom/workspace/coding/xxx-emulator-v2/TR/client/bin/a.out 
019e5000-01a07000 rw-p 00000000 00:00 0         [heap] 
7f767aed5000-7f767aed6000 r-xp 00000000 08:01 304337      /home/tom/workspace/coding/xxx-emulator-v2/TR/client/bin/yyy.so 
7f767aed6000-7f767b0d5000 ---p 00001000 08:01 304337      /home/tom/workspace/coding/xxx-emulator-v2/TR/client/bin/yyy.so 
7f767b0d5000-7f767b0d6000 r--p 00000000 08:01 304337      /home/tom/workspace/coding/xxx-emulator-v2/TR/client/bin/yyy.so 
7f767b0d6000-7f767b0d7000 rw-p 00001000 08:01 304337      /home/tom/workspace/coding/xxx-emulator-v2/TR/client/bin/yyy.so 
7f767b0d7000-7f767b292000 r-xp 00000000 08:01 791296      /lib/x86_64-linux-gnu/libc-2.19.so 
7f767b292000-7f767b492000 ---p 001bb000 08:01 791296      /lib/x86_64-linux-gnu/libc-2.19.so 
7f767b492000-7f767b496000 r--p 001bb000 08:01 791296      /lib/x86_64-linux-gnu/libc-2.19.so 
7f767b496000-7f767b498000 rw-p 001bf000 08:01 791296      /lib/x86_64-linux-gnu/libc-2.19.so 
7f767b498000-7f767b49d000 rw-p 00000000 00:00 0 
7f767b49d000-7f767b4a0000 r-xp 00000000 08:01 791313      /lib/x86_64-linux-gnu/libdl-2.19.so 
7f767b4a0000-7f767b69f000 ---p 00003000 08:01 791313      /lib/x86_64-linux-gnu/libdl-2.19.so 
7f767b69f000-7f767b6a0000 r--p 00002000 08:01 791313      /lib/x86_64-linux-gnu/libdl-2.19.so 
7f767b6a0000-7f767b6a1000 rw-p 00003000 08:01 791313      /lib/x86_64-linux-gnu/libdl-2.19.so 
7f767b6a1000-7f767b6c4000 r-xp 00000000 08:01 791272      /lib/x86_64-linux-gnu/ld-2.19.so 
7f767b8aa000-7f767b8ad000 rw-p 00000000 00:00 0 
7f767b8c0000-7f767b8c3000 rw-p 00000000 00:00 0 
7f767b8c3000-7f767b8c4000 r--p 00022000 08:01 791272      /lib/x86_64-linux-gnu/ld-2.19.so 
7f767b8c4000-7f767b8c5000 rw-p 00023000 08:01 791272      /lib/x86_64-linux-gnu/ld-2.19.so 
7f767b8c5000-7f767b8c6000 rw-p 00000000 00:00 0 
7fff85cb4000-7fff85cd5000 rw-p 00000000 00:00 0       [stack] 
7fff85ce5000-7fff85ce7000 r-xp 00000000 00:00 0       [vdso] 
7fff85ce7000-7fff85ce9000 r--p 00000000 00:00 0       [vvar] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 
note: sections in order: .text, .rodata, .bss 
Inside Enclave now 
Killed 


@dmesg 
[ 87.913346] Local XXX Handler Called from PID: 2877 EIP: 0x 400bfd 
[ 87.913349] Hooked an EENTER instruction. 
[ 87.913350] TT: Done hooking EENTER: rbx:00000000019e5010, rdx:00000000019e6020 
[ 87.913353] Syscall inside Enclave hooked! NR=1, i=5 
[ 87.913355] Caller process: pid: 2877, tid: 2877, comm: a.out, 
[ 87.913355]       uid: 1000, gid: 1000, euid: 18446744069414585320 
[ 87.913355]       suid: 140144782869480, sgid: 1000, fsuid: 140144782869480, fsgid: 1000, user: 1000, 
[ 87.913357] Caller context: ret_addr: 00007f767b8aa740, filename to open():/proc/self/maps 
[ 87.913360] Syscall inside Enclave hooked! NR=2, i=6 
[ 87.913362] Caller process: pid: 2877, tid: 2877, comm: a.out, 
[ 87.913362]       uid: 1000, gid: 1000, euid: 18446612132314219496 
[ 87.913362]       suid: 18446744069414585320, sgid: 1000, fsuid: 1000, fsgid: 1000, user: 140144782869480, 
[ 87.913364] Caller context: ret_addr: 00007fff85cd35e8, filename to open():temp.txt 
[ 87.913378] invalid opcode: 0000 [#1] SMP 
[ 87.913380] Modules linked in: xxx(OE) nls_utf8 isofs vboxsf(OE) snd_intel8x0 snd_ac97_codec ac97_bus snd_pcm snd_seq_midi snd_seq_midi_event hid_generic snd_rawmidi joydev snd_seq snd_seq_device snd_timer usbhid hid snd rfcomm bnep bluetooth 6lowpan_iphc serio_raw vboxvideo(OE) i2c_piix4 vboxguest(OE) soundcore drm parport_pc mac_hid ppdev lp parport psmouse ahci libahci e1000 pata_acpi 
[ 87.913401] CPU: 0 PID: 2877 Comm: a.out Tainted: G   OE 3.16.0-30-generiC#40~14.04.1-Ubuntu 
[ 87.913402] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 
[ 87.913404] task: ffff88002cf67010 ti: ffff88002bd94000 task.ti: ffff88002bd94000 
[ 87.913405] RIP: 03e8:[<ffffffffc01d342a>] [<ffffffffc01d342a>] hook+0x12a/0x134 [xxx] 
[ 87.913409] RSP: 03e8:00000000000003e8 EFLAGS: ffffffff000003e8 
[ 87.913410] RAX: 0000000000000049 RBX: ffff88002cf67010 RCX: 0000000000000006 
[ 87.913411] RDX: 0000000000000007 RSI: 0000000000000046 RDI: 0000000000000246 
[ 87.913412] RBP: ffff88002bd97f50 R08: 0000000000000082 R09: 0000000000000214 
[ 87.913413] R10: 0000000000000000 R11: ffff88002bd97c2e R12: 0000000000000241 
[ 87.913414] R13: 00000000000001b6 R14: 0000000000000000 R15: 0000000000000000 
[ 87.913416] FS: 00007f767b8aa740(0000) GS:ffff88003fc00000(0000) knlGS:0000000000000000 
[ 87.913417] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 
[ 87.913419] CR2: 00007f767b24eee4 CR3: 0000000036cb7000 CR4: 00000000000006f0 
[ 87.913423] Stack: 
[ 87.913426] BUG: unable to handle kernel NULL pointer dereference at 00000000000003e8 
[ 87.913428] IP: [<ffffffff81015a29>] show_stack_log_lvl+0x109/0x180 
[ 87.913434] PGD 3ab9a067 PUD 2ed84067 PMD 0 


[ 87.913437] Oops: 0000 [#2] SMP 
[ 87.913438] Modules linked in: xxx(OE) nls_utf8 isofs vboxsf(OE) snd_intel8x0 snd_ac97_codec ac97_bus snd_pcm snd_seq_midi snd_seq_midi_event hid_generic snd_rawmidi joydev snd_seq snd_seq_device snd_timer usbhid hid snd rfcomm bnep bluetooth 6lowpan_iphc serio_raw vboxvideo(OE) i2c_piix4 vboxguest(OE) soundcore drm parport_pc mac_hid ppdev lp parport psmouse ahci libahci e1000 pata_acpi 
[ 87.913452] CPU: 0 PID: 2877 Comm: a.out Tainted: G   OE 3.16.0-30-generiC#40~14.04.1-Ubuntu 
[ 87.913453] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006 
[ 87.913454] task: ffff88002cf67010 ti: ffff88002bd94000 task.ti: ffff88002bd94000 
[ 87.913455] RIP: 0010:[<ffffffff81015a29>] [<ffffffff81015a29>] show_stack_log_lvl+0x109/0x180 
[ 87.913457] RSP: 0018:ffff88002bd97c60 EFLAGS: 00010046 
[ 87.913458] RAX: 00000000000003f0 RBX: 00000000000003e8 RCX: 0000000000000000 
[ 87.913459] RDX: ffff88003fc03fc0 RSI: ffff88002bd97e88 RDI: 0000000000000000 
[ 87.913460] RBP: ffff88002bd97cb0 R08: ffff88003fbfffc0 R09: 0000000000000224 
[ 87.913461] R10: 0000000000000000 R11: ffff88002bd979de R12: ffff88002bd97e88 
[ 87.913462] R13: 0000000000000000 R14: ffffffff81a64864 R15: 0000000000000000 
[ 87.913464] FS: 00007f767b8aa740(0000) GS:ffff88003fc00000(0000) knlGS:0000000000000000 
[ 87.913465] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 
[ 87.913466] CR2: 00000000000003e8 CR3: 0000000036cb7000 CR4: 00000000000006f0 
[ 87.913466] Stack: 
[ 87.913467] ffffffff8175b59b ffff880000000008 ffff88002bd97cc0 ffff88002bd97c80 
[ 87.913469] 00000000000003e8 ffff88002bd97e88 00000000000003e8 0000000000000040 
[ 87.913471] 0000000000000000 0000000000000006 ffff88002bd97cf0 ffffffff81015b2a 
[ 87.913473] Call Trace: 
[ 87.913478] [<ffffffff8175b59b>] ? printk+0x67/0x69 
[ 87.913480] [<ffffffff81015b2a>] show_regs+0x8a/0x200 
[ 87.913482] [<ffffffff810169bf>] __die+0x9f/0xe0 
[ 87.913484] [<ffffffff81016e48>] die+0x38/0x70 
[ 87.913486] [<ffffffff81013400>] do_trap+0xb0/0x150 
[ 87.913489] [<ffffffff81013ac7>] do_error_trap+0x97/0x150 
[ 87.913491] [<ffffffffc01d342a>] ? hook+0x12a/0x134 [xxx] 
[ 87.913496] [<ffffffff810c8bb4>] ? wake_up_klogd+0x34/0x50 
[ 87.913498] [<ffffffff810c8dc8>] ? console_unlock+0x1f8/0x440 
[ 87.913500] [<ffffffff81014140>] do_invalid_op+0x20/0x30 
[ 87.913503] [<ffffffffc01d32f2>] intr_handler+0x12/0x20 [xxx] 
[ 87.913505] [<ffffffffc01d3465>] intr_stub+0x15/0x20 [xxx] 
[ 87.913507] [<ffffffffc01d342a>] ? hook+0x12a/0x134 [xxx] 
[ 87.913509] [<ffffffffc01d3493>] new_sys_open+0x23/0x40 [xxx] 
[ 87.913512] [<ffffffff8176aced>] system_call_fastpath+0x1a/0x1f 
[ 87.913513] Code: 4d b8 4c 89 45 c0 48 89 55 c8 48 8b 5b f8 e8 23 5b 74 00 48 8b 55 c8 4c 8b 45 c0 8b 4d b8 85 c9 74 05 f6 c1 03 74 4c 48 8d 43 08 <48> 8b 33 48 c7 c7 5c 48 a6 81 89 4d b4 4c 89 45 b8 48 89 45 c8 
[ 87.913531] RIP [<ffffffff81015a29>] show_stack_log_lvl+0x109/0x180 
[ 87.913534] RSP <ffff88002bd97c60> 
[ 87.913535] CR2: 00000000000003e8 
[ 87.913537] ---[ end trace 38675fa903317736 ]--- 

ответ

1

То, что вы хотите сделать, это очень необычно, и это не удивительно, что он выходит из строя операционной системы.

Обработчики прерываний не должны вызываться непосредственно из другого кода. Во-первых, они не возвращаются так, как возвращается обычная функция С. На x86 обработчики прерываний возвращаются с инструкцией RETI, которая рассчитывает найти сохраненные значения регистров в стеке. (Это не может быть сделано на языке C и требуется код языка ассемблера. См. arch/x86/kernel/entry_32.S, чтобы увидеть код обработки и возврата прерываний на низком уровне для x86-32.) Если вы попытаетесь вызвать обработчик прерываний из другого кода C, когда обработчик вернется , он будет принимать все «мусор», которые он находит в стеке, и загружать их в ваши регистры, включая указатель стека и указатель инструкции.

Если вы объясните, почему вы хотите это сделать, возможно, кто-то может помочь вам найти альтернативный способ выполнить то, что вы на самом деле хотите достичь.

EDIT:

Я думал, вы звонили непосредственно в обработчик прерывания, но теперь я вижу, что do_invalid_op это просто функция C, которая вызывается из обработчика прерываний. Однако почему вы называете это без аргументов? Вот как это определено в края Linux:

#define DO_ERROR(trapnr, signr, str, name)    \ 
dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \ 
{         \ 
    do_error_trap(regs, error_code, str, trapnr, signr);  \ 
} 

DO_ERROR(X86_TRAP_UD,  SIGILL, "invalid opcode",  invalid_op) 

Таким образом, вы должны пройти 2 арг, а struct pt_regs* и long. Неужели это все еще сбой, если вы это сделаете?

+0

кажется разумным. похоже, что BOTH и возврат обработчика прерываний должны проходить через asm/register manipulation ... получили его. Вещь, которую я хочу сделать, это просто вызвать код внутри 'do_invalid_op()' (без инструкции RETI' в конце, хотя ...) – Richard

+0

хорошее редактирование. то, что я на самом деле вызывал, это 'invalid_op()' (версия без аргумента 'do_invalid_op (...)') ... и она все еще сбой – Richard

+0

Первая часть моего ответа адресована этому. 'invalid_op' - это вектор прерывания. Вы не можете вызвать это непосредственно из C. –

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