CONFIG_ARM64_PAN

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/tiantao2012/article/details/100085068
CONFIG_ARM64_PAN 是armv8.1的一个扩展特性,其全称是Privileged Access Never,作用是kernel和userspace 不能同时访问一段内存.原文是When enabled, this feature causes a permission fault if the kernel attempts to access memory that is also accessible by userspace - instead the PAN bit must be cleared when accessing userspace memory.
对应的lkm是https://lwn.net/Articles/651614/

这个patch 在4.2的时候被合入主线
/kernel/kernel$ git describe  338d4f49d6f7
v4.2-rc4-27-g338d4f49d6f7

那这个feature 具体是怎么工作的呢?
这里以copy_from_user来举例
 ENTRY(__copy_from_user)
+ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, \
+           CONFIG_ARM64_PAN)
        add     x5, x1, x2                      // upper user buffer boundary
        subs    x2, x2, #16
        b.mi    1f
@@ -56,6 +62,8 @@ USER(9f, ldrh w3, [x1], #2    )
 USER(9f, ldrb  w3, [x1]        )
        strb    w3, [x0]
 5:     mov     x0, #0
+ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(1)), ARM64_HAS_PAN, \
+           CONFIG_ARM64_PAN)
        ret
 ENDPROC(__copy_from_user)

可以看到有增加ALTERNATIVE("nop", __stringify(SET_PSTATE_PAN(0)), ARM64_HAS_PAN, CONFIG_ARM64_PAN)
其中ARM64_HAS_PAN是宏,定义在#define ARM64_HAS_PAN				4
这句话的意思是如果定义CONFIG_ARM64_PAN,则执行__stringify(SET_PSTATE_PAN(0)),否则执行"nop"执行
#define SET_PSTATE_PAN(x) __inst_arm(0xd5000000 | REG_PSTATE_PAN_IMM | (!!x)<<8 | 0x1f)
这里的也就是讲pan 对应的bit 置0,为啥要置零呢?这是规定,当kernel访问用户态内存是就pan对应的bit位清零
this feature causes a permission fault if the kernel attempts to access memory that is also accessible by userspace - instead the
PAN bit must be cleared when accessing userspace memory

如果真发生kernel 访问用户态内存,但是PAN 对应的bit 位为1的情况的话,则会发生fault
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -30,9 +30,11 @@
 #include <linux/highmem.h>
 #include <linux/perf_event.h>

+#include <asm/cpufeature.h>
 #include <asm/exception.h>
 #include <asm/debug-monitors.h>
 #include <asm/esr.h>
+#include <asm/sysreg.h>
 #include <asm/system_misc.h>
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -223,6 +225,13 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
                mm_flags |= FAULT_FLAG_WRITE;
        }

+       /*
+        * PAN bit set implies the fault happened in kernel space, but not
+        * in the arch's user access functions.
+        */
#使能PAN 特性,且PSR_PAN_BIT为1,说明kernel 准备访问的虚拟内存用户态也在访问
+       if (IS_ENABLED(CONFIG_ARM64_PAN) && (regs->pstate & PSR_PAN_BIT))
+               goto no_context;
+

猜你喜欢

转载自blog.csdn.net/tiantao2012/article/details/100085068