【问题标题】:Delayed Linux kernel panic when change the PFN in a PTE更改 PTE 中的 PFN 时延迟 Linux 内核恐慌
【发布时间】: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_addr1virt_addr2 页面是否对齐(也许这是一个愚蠢的问题)?使用__get_free_page()free_page() 有什么不同吗?
  • 好点。我使用了 kmalloc,virt_addr1 和 virt_addr2 都是页面对齐的。我尝试使用页面的 API,我得到了同样的错误。不知道PTE/page struct里面有没有其他内核组件引用的,修改PTE字段后可能会触发crash。

标签: memory-management linux-kernel


【解决方案1】:

通过大量测试和重新启动,我想我找到了解决恐慌的方法。
之间
6.将virt_addr2的PTE改回原来的PFN。
7. kfree(virt_addr1) 和 kfree(virt_addr2);
将 PTE 改回原来的 PFN 后,需要再次刷新 TLB。

通过此 TLB 刷新,不再出现 PANIC。
我不知道背后的原因,如果有人可以分享更多细节,那就太好了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2021-01-13
    • 1970-01-01
    • 2020-01-28
    相关资源
    最近更新 更多