当前位置:   article > 正文

ARM64 内核PXN机制验证测试_arm pxn

arm pxn

PXN简介

PXN全称 Privileged Execute-Never,是一种内核安全特性,用来阻止内核直接执行用户空间的代码,能够极大地提升漏洞利用的难度。

根据kernelsec网站的描述,armv8及以上版本的PXN特性由硬件支持,各平台和架构的PXN特性见下图:

(表格内容来自Linux Kernel Security Subsystem

 结合对linux源码(内核版本5.10.41)的分析可以发现,PXN和UXN机制均通过寄存器中的一个位进行控制,具体实现如下:

  1. arch/arm64/include/asm/pgtable-hwdef.h
  2. /*
  3. * Level 3 descriptor (PTE).
  4. */
  5. #define PTE_PXN (_AT(pteval_t, 1) << 53) /* Privileged XN */
  6. #define PTE_UXN (_AT(pteval_t, 1) << 54) /* User XN */

因为PXN特性取决于硬件平台是否支持,所以即使我们看到代码中有对应的实现,并不代表这个功能在系统上是有效的,因此需要进一步构造测试案例来验证。

构造测试案例

编写内核模块,在内核模块中创建proc文件系统,通过proc_write接口向内核空间传递用户空间的代码地址,然后尝试在内核空间中直接执行来自用户空间的代码。

kernel模块主要逻辑实现如下:

  1. static ssize_t mywrite(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos)
  2. {
  3. char buf[MAX_LENGTH];
  4. typedef void (*MY_FUNC_P)(void);
  5. printk(KERN_INFO "********************* dump stack **********************\n");
  6. dump_stack();
  7. ((MY_FUNC_P)ubuf)();
  8. return count;
  9. }

用户空间主要逻辑实现如下:

  1. void
  2. payload(void)
  3. {
  4. if (getuid() == 0) {
  5. printf("[+] PXN is gone, how dare you!\n");
  6. execl("/bin/sh", "sh", NULL);
  7. } else {
  8. warnx("this will never be execute.");
  9. }
  10. _exit(0);
  11. }
  12. extern uint32_t shellCode[];
  13. asm
  14. (
  15. " .text\n"
  16. " .align 2\n"
  17. " .globl shellCode\n\t"
  18. "shellCode:\n\t"
  19. "bl #payload\n\t"
  20. );
  21. void
  22. trigger_vuln(int fd, int canary)
  23. {
  24. #define MAX_PAYLOAD (MAX + 4 * 4 )
  25. char buf[MAX_PAYLOAD];
  26. memset(buf, 0, sizeof(buf));
  27. void * pc = buf ;
  28. *(void **)pc = (void *) shellCode;
  29. write(fd, buf, sizeof(buf) );
  30. printf("[+] write done, %d bytes\n", sizeof(buf));
  31. }

通过执行测试案例,我们的预期结果是kernel在执行用户空间代码时抛出异常提示,但如果用户空间的测试程序执行之后输出"[+] PXN is gone, how dare you!\n",则表示PXN没有生效。

测试结果

安装内核模块:

  1. vcu-sxxx:/home# insmod lkm_pxn.ko 
  2. vcu-sxxx:/home# [   49.457010] hello...

执行用户空间程序:

  1. vcu-sxxxxx:/home# chmod +x uspace
  2. vcu-sxxxxx:/home# ./uspace
  3. [ 61.084617] ********************* dump stack **********************
  4. [ 61.084642] CPU: 3 PID: 1474 Comm: uspace Tainted: G O 5.10.41-rt42+g5c4c385db992 #1
  5. [ 61.084658] Hardware name: ARM vcu-sxxxxx(DT)
  6. [ 61.084663] Call trace:
  7. [ 61.084665] dump_backtrace+0x0/0x180
  8. [ 61.084686] show_stack+0x18/0x70
  9. [ 61.084695] dump_stack+0xd0/0x12c
  10. [ 61.084707] mywrite+0x2c/0xd8 [lkm_pxn]
  11. [ 61.084720] proc_reg_write+0xa8/0xec
  12. [ 61.084731] vfs_write+0xf0/0x2b0
  13. [ 61.084743] ksys_write+0x58/0xe0
  14. [ 61.084751] __arm64_sys_write+0x20/0x30
  15. [ 61.084760] el0_svc_common.constprop.0+0x78/0x1a0
  16. [ 61.084772] do_el0_svc+0x24/0x90
  17. [ 61.084780] el0_svc+0x14/0x20
  18. [ 61.084790] el0_sync_handler+0x1a4/0x1b0
  19. [ 61.084797] el0_sync+0x180/0x1c0
  20. [ 61.084810] Unable to handle kernel execution of user memory at virtual address 0000007fd808ce58
  21. [ 61.165015] Mem abort info:
  22. [ 61.165014] printk: console [ttyLF0]: printing thread stopped
  23. [ 61.167933] ESR = 0x8600000f
  24. [ 61.176923] EC = 0x21: IABT (current EL), IL = 32 bits
  25. [ 61.182402] SET = 0, FnV = 0
  26. [ 61.185549] EA = 0, S1PTW = 0
  27. [ 61.188788] user pgtable: 4k pages, 39-bit VAs, pgdp=000000009709d000
  28. [ 61.195406] [0000007fd808ce58] pgd=000000008c39b003, p4d=000000008c39b003, pud=000000008c39b003, pmd=0000000081f30003, pte=00e8000086663f43
  29. [ 61.208308] Internal error: Oops: 8600000f [#1] PREEMPT_RT SMP
  30. [ 61.214289] Modules linked in: lkm_pxn(O) pfeng(O)
  31. [ 61.219205] CPU: 3 PID: 1474 Comm: uspace Tainted: G O 5.10.41-rt42+g5c4c385db992 #1
  32. [ 61.228482] Hardware name: ARM XXXXX (DT)
  33. [ 61.233300] pstate: 40000005 (nZcv daif -PAN -UAO -TCO BTYPE=--)
  34. [ 61.239457] pc : 0x7fd808ce58
  35. [ 61.242501] lr : mywrite+0xb4/0xd8 [lkm_pxn]
  36. [ 61.246882] sp : ffffffc01235b980
  37. [ 61.250275] x29: ffffffc01235b980 x28: ffffff8001d29a80
  38. [ 61.255721] x27: 0000000000000000 x26: 0000000000000000
  39. [ 61.261165] x25: 0000000000000000 x24: 0000000000000000
  40. [ 61.266609] x23: 0000000000000000 x22: ffffffc01235be38
  41. [ 61.272052] x21: 0000007fd808ce58 x20: 0000007fd808ce58
  42. [ 61.277497] x19: 0000000000000050 x18: 00000000fffffffa
  43. [ 61.282941] x17: 0000000000000000 x16: 0000000000000000
  44. [ 61.288385] x15: 0000000000000020 x14: 4141414141414141
  45. [ 61.293828] x13: 4141414141414141 x12: 4141414141414141
  46. [ 61.299272] x11: 4141414141414141 x10: 4141414141414141
  47. [ 61.304715] x9 : 4141414141414141 x8 : 4141414141414141
  48. [ 61.310160] x7 : 4141414141414141 x6 : ffffffc01235b9f0
  49. [ 61.315603] x5 : ffffffc01235b9f0 x4 : 0000000000000008
  50. [ 61.321048] x3 : 858d0cd041414141 x2 : 0000000000000000
  51. [ 61.326493] x1 : 0000007fd808cea8 x0 : 0000000000000000
  52. [ 61.331938] Call trace:
  53. [ 61.334442] 0x7fd808ce58
  54. [ 61.337127] proc_reg_write+0xa8/0xec
  55. [ 61.340886] vfs_write+0xf0/0x2b0
  56. [ 61.344289] ksys_write+0x58/0xe0
  57. [ 61.347688] __arm64_sys_write+0x20/0x30
  58. [ 61.351709] el0_svc_common.constprop.0+0x78/0x1a0
  59. [ 61.356623] do_el0_svc+0x24/0x90
  60. [ 61.360020] el0_svc+0x14/0x20
  61. [ 61.363154] el0_sync_handler+0x1a4/0x1b0
  62. [ 61.367262] el0_sync+0x180/0x1c0
  63. [ 61.370667] Code: 00000000 00000000 000000ac 00000000 (41414141)
  64. [ 61.376915] ---[ end trace 0000000000000002 ]---
  65. Segmentation fault

从日志“Unable to handle kernel execution of user memory at virtual address”可以确认,内核PXN机制阻止了此次用户空间代码的执行。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/684760
推荐阅读
  

闽ICP备14008679号