在我的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:更新示例代码以反映我打算让模块执行的操作;一旦error_found
,内核执行应该跳转到某个地方(例如用户空间)而不运行其余的模块初始化代码。
更新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 ]---
答案 0 :(得分:1)
你想要做的事情是非常不寻常的,它会使操作系统崩溃并不奇怪。
中断处理程序不能直接从其他代码调用。首先,它们不会以普通C函数返回的方式返回。在x86上,中断处理程序返回RETI
指令,该指令希望在堆栈上找到已保存的寄存器值。 (这不能在C中完成并且需要汇编语言代码。请参阅arch/x86/kernel/entry_32.S
以查看低级中断处理并返回x86-32的代码。)如果您尝试从其他C代码调用中断处理程序,当处理程序返回时,它将获取它在堆栈中找到的任何“垃圾”并将其加载到寄存器中,包括堆栈指针和指令指针。
如果你解释为什么要这样做,也许有人可以帮助你找到另一种方法来完成你真正想要完成的事情。
修改强>
我以为你直接调用了一个中断处理程序,但现在我看到do_invalid_op
只是一个从中断处理程序调用的C函数。但是,你为什么不用args来调用它呢?以下是它在边缘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
。如果你这样做,它仍会崩溃吗?