oops实例分析


源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h>

MODULE_DESCRIPTION("Oops generating module");
MODULE_AUTHOR("So2rul Esforever");
MODULE_LICENSE("GPL");

static int my_oops_init(void)
{
char *p = 0;

pr_info("before init\n");
*p = 'a';
pr_info("after init\n");

return 0;
}

static void my_oops_exit(void)
{
pr_info("module goes all out\n");
}

module_init(my_oops_init);
module_exit(my_oops_exit);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
root@qemux86:~/skels/kernel_modules/5-oops-mod# insmod oops_mod.ko              
before init
BUG: kernel NULL pointer dereference, address: 00000000
#PF: supervisor write access in kernel mode
#PF: error_code(0x0002) - not-present page
*pde = 00000000
Oops: 0002 [#1] SMP
CPU: 0 PID: 392 Comm: insmod Tainted: G O 5.10.14+ #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04
EIP: my_oops_init+0xd/0x22 [oops_mod]
Code: Unable to access opcode bytes at RIP 0xe0830fe3.
EAX: 0000000b EBX: 00000000 ECX: dfbc9d6c EDX: 0110a049
ESI: e0831000 EDI: 00000002 EBP: c2975dd8 ESP: c2975dd4
DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00000282
CR0: 80050033 CR2: e0830fe3 CR3: 04318000 CR4: 00000690
Call Trace:
do_one_initcall+0x57/0x2d0
? rcu_read_lock_sched_held+0x47/0x80
? kmem_cache_alloc_trace+0x2ed/0x370
? do_init_module+0x1f/0x210
do_init_module+0x4e/0x210
load_module+0x20a4/0x2580
__ia32_sys_init_module+0xed/0x130
do_int80_syscall_32+0x2c/0x40
entry_INT80_32+0xf7/0xf7
EIP: 0x44902cc2
Code: 06 89 8a 84 01 00 00 c3 55 57 56 53 8b 6c 24 2c 8b 7c 24 28 8b 74 24 24 80
EAX: ffffffda EBX: 081e0050 ECX: 0001cfdc EDX: 081e0008
ESI: 00000000 EDI: bfe4f23c EBP: 00000000 ESP: bfe4f09c
DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 007b EFLAGS: 00000206
Modules linked in: oops_mod(O+) [last unloaded: multi_mod]
CR2: 0000000000000000
---[ end trace d98f6afbdbaeab25 ]---
EIP: my_oops_init+0xd/0x22 [oops_mod]
Code: Unable to access opcode bytes at RIP 0xe0830fe3.
EAX: 0000000b EBX: 00000000 ECX: dfbc9d6c EDX: 0110a049
ESI: e0831000 EDI: 00000002 EBP: c2975dd8 ESP: c2975dd4
DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00000282
CR0: 80050033 CR2: e0830fe3 CR3: 04318000 CR4: 00000690
Killed

3:错误原因:空指针引用
4:内核模式下的写模式
10:错误函数:my_oops_init,偏移0xd
23:调用栈Call Trace:__ia32_sys_init_module

反汇编

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
objdump -d oops_mod.ko                              

oops_mod.ko: file format elf32-i386

Disassembly of section .text.unlikely:

00000000 <init_module>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 68 00 00 00 00 push $0x0
8: e8 fc ff ff ff call 9 <init_module+0x9>
d: c6 05 00 00 00 00 61 movb $0x61,0x0
14: 68 0f 00 00 00 push $0xf
19: e8 fc ff ff ff call 1a <init_module+0x1a>
1e: 31 c0 xor %eax,%eax
20: c9 leave
21: c3 ret

00000022 <cleanup_module>:
22: 55 push %ebp
23: 89 e5 mov %esp,%ebp
25: 68 1d 00 00 00 push $0x1d
2a: e8 fc ff ff ff call 2b <cleanup_module+0x9>
2f: 58 pop %eax
30: c9 leave
31: c3 ret

在0xd偏移初正是 *p = ‘a’ ,0x61是’a’