浅谈 | Intel MPK
浅谈 | Intel MPK
在阅读本篇内容前,需要读者对 x64 架构有基本的了解。
引言
Intel MPK(Memory Protection Keys)是一种轻量级内存保护机制,它的核心优势在于无需修改页表,即可动态控制内存页的访问权限,这避免了传统内存权限修改页表项需要刷新 TLB 所带来的性能开销。
配置
| 功能 | 支持 | 控制寄存器 |
|---|---|---|
| PKU | CPUID.(EAX=07H, ECX=0H):ECX.OSPKE [Bit 4] | CR4.PKE |
| PKS | CPUID.(EAX=07H, ECX=0H):ECX.PKS [Bit 31] | CR4.PKS |
- 启用 PKU 以后,配置 PKRU 和 Protection Key,即可控制 User-Mode 页面的访问权限。
- 启用 PKS 以后,配置 IA32_PKRS 和 Protection Key,即可控制 Supervisor-Mode 页面的访问权限。
PKRU 与 IA32_PKRS 的结构基本相同,都是 32 位有效位,包含 16 对 ADi 与 WDi,具体布局如下:
1
2
3
4
┌──────┬──────┬──────┬──────┬─────┬─────┬─────┬─────┬─────┐
│ AD15 │ WD15 │ AD14 │ WD14 │ ... │ AD1 │ WD1 │ AD0 │ WD0 │
└──────┴──────┴──────┴──────┴─────┴─────┴─────┴─────┴─────┘
31 30 29 28 3 2 1 0
- ADi(Access Disable)为 1 时禁止数据读写,但 取指 操作不受影响。
- WDi(Write Disable)为 1 时禁止数据写入。
当启用 PKU 或 PKS 以后,对应模式的页表项中的 Bit 62:59 用于存储 Protection Key,取值范围是 0~15,对应的便是 ADi 与 WDi 中的 i。
PKRU 可以通过两个新增的指令 RDPKRU 与 WRPKRU 访问,也可以通过设置 XCR0,调用 XSAVE 与 XRSTOR 指令进行访问;而 IA32_PKRS 是 MSR,需使用 RDMSR 和 WRMSR 来进行访问。
异常
处理器在进行 Page Walk 的时候,如果违反 Protection Key 权限,会产生 #PF 异常,可通过检查 PFEC(Page Fault Error Code)的 Bit 5 来判断是否由 Protection Key 引发。
结尾
聪明的挂哥可能想到了,取指 操作不受 Protection Key 影响,意味着可以分离读写与执行权限,在使用所谓的 无痕 HOOK 的时候,性能可以大幅度提高,Intel VT-x 的 EPT 可以轻松的完成这项任务,但是 AMD-V 的 NPT 并没有这样的功能,那么 NPT 结合 Protection Key 是否可以实现呢?答案就在下面,诸位细品。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
nt!_HARDWARE_PTE
+0x000 Valid : Pos 0, 1 Bit
+0x000 Write : Pos 1, 1 Bit
+0x000 Owner : Pos 2, 1 Bit
+0x000 WriteThrough : Pos 3, 1 Bit
+0x000 CacheDisable : Pos 4, 1 Bit
+0x000 Accessed : Pos 5, 1 Bit
+0x000 Dirty : Pos 6, 1 Bit
+0x000 LargePage : Pos 7, 1 Bit
+0x000 Global : Pos 8, 1 Bit
+0x000 CopyOnWrite : Pos 9, 1 Bit
+0x000 Prototype : Pos 10, 1 Bit
+0x000 reserved0 : Pos 11, 1 Bit
+0x000 PageFrameNumber : Pos 12, 40 Bits
+0x000 SoftwareWsIndex : Pos 52, 11 Bits
+0x000 NoExecute : Pos 63, 1 Bit
This post is licensed under CC BY 4.0 by the author.
