【发布时间】:2020-01-16 09:03:59
【问题描述】:
我正在运行一个内核模块,但在卸载该模块一段时间后,我遇到了内核崩溃。
内核模块做了几件事。
1. virt_addr1 = kmalloc(4096);
2. virt_addr2 = kmalloc(4096);
3. 找到 virt_addr1 和 virt_addr2 的 PTE。
4.设置virt_addr1的PFN为virt_addr2的PTE,所以virt_addr2和virt_addr1基本指向同一个PFN和page。
5.调用invlpg刷新TLB。
6.将virt_addr2的PTE改回原来的PFN。
7. kfree(virt_addr1) 和 kfree(virt_addr2);
8. 卸载模块。
在模块目录中运行'make',然后内核崩溃如下,
[ 1980.579451] RIP: 0010:[<ffffffff811ff44a>] [<ffffffff811ff44a>] getname_kernel+0xda/0x120
[ 1980.583728] RSP: 0018:ffff8804a596bd38 EFLAGS: 00010283
[ 1980.586396] RAX: 1111111111111111 RBX: 1111111111111111 RCX: 0000000000000000
[ 1980.590111] RDX: 000000000001bd58 RSI: 1111111111111111 RDI: 111111111111112d
[ 1980.593795] RBP: ffff8804a596bd58 R08: ffff8804a0dfbc00 R09: 0000000000000000
[ 1980.597418] R10: 2d3638782d78756e R11: 00322e6f732e3436 R12: 000000000000001c
[ 1980.601093] R13: fffffffffffffff4 R14: ffff8804a1380f20 R15: ffff8804a1bee038
[ 1980.604736] FS: 00007efd1517c700(0000) GS:ffff8804bd940000(0000) knlGS:0000000000000000
[ 1980.608942] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1980.611885] CR2: 00007fb42fc7ad0c CR3: 00000004a5864000 CR4: 00000000001406e0
[ 1980.615509] Stack:
[ 1980.616565] ffff8800ba1fb380 ffff8804a0dfae00 00000000fffffff8 ffff8804a596c000
[ 1980.620540] ffff8804a596bd78 ffffffff811f5b91 ffff8800ba1fb380 ffff8804a0dfae00
[ 1980.624527] ffff8804a596be60 ffffffff81249e4c 0000000000000000 0000000000000000
[ 1980.628518] Call Trace:
[ 1980.629791] [<ffffffff811f5b91>] open_exec+0x11/0x50
[ 1980.632362] [<ffffffff81249e4c>] load_elf_binary+0x2bc/0x1710
[ 1980.635288] [<ffffffff811a0222>] ? get_user_pages+0x52/0x60
[ 1980.638132] [<ffffffff811f610e>] search_binary_handler+0x9e/0x1d0
[ 1980.641241] [<ffffffff811f79dc>] do_execveat_common.isra.36+0x52c/0x710
[ 1980.645204] [<ffffffff811f7e5a>] SyS_execve+0x3a/0x50
[ 1980.648518] [<ffffffff81804ba5>] stub_execve+0x5/0x5
[ 1980.651829] [<ffffffff8180491b>] ? entry_SYSCALL_64_fastpath+0x16/0x6a
[ 1980.655781] Code: 80 80 06 00 00 48 85 c0 74 0e 8b 00 85 c0 75 08 48 89 df e8 69 e7 f0 ff 49 89 dd 5b 4c 89 e8 41 5c 41 5d 41 5e 5d c3 48 8d 78 1c <48> 89 38 eb a3 48 8b 3d ca 34 d3 00 48 89 c6 49 c7 c5 dc ff ff
【问题讨论】:
-
virt_addr1和virt_addr2页面是否对齐(也许这是一个愚蠢的问题)?使用__get_free_page()和free_page()有什么不同吗? -
好点。我使用了 kmalloc,virt_addr1 和 virt_addr2 都是页面对齐的。我尝试使用页面的 API,我得到了同样的错误。不知道PTE/page struct里面有没有其他内核组件引用的,修改PTE字段后可能会触发crash。
标签: memory-management linux-kernel