【操作系统百科】特权级与硬件隔离
CPU 是唯一能强制执行”用户态不能做什么”的东西。OS
把软件抽象(进程、namespace、capability)最终都要落到 CPU
提供的硬件原语——特权级、分页、某些特殊指令的拦截——才算数。如果
CPU 的隔离机制失效(Meltdown
就是经典例子),再完美的软件隔离都会被一句
mov rax, [kernel_addr] 破掉。
本文把 CPU 给 OS 的隔离原语梳理清楚。按层次从”经典”到”现代缓解”:特权级本体 → 页表保护位 → SMEP/SMAP/PAN → KASLR/KPTI → CET / BTI / MTE → PKU/PKRU → 硬件加密内存 → VMX root/non-root → SMM/TrustZone。每一项挡的攻击类型不同,组合起来构成了现代系统的”深度防御”。
下面这张图把 x86 / ARMv8 / RISC-V 三家的特权级层次并排摆出,方便比较:
flowchart TB
subgraph x86[x86_64]
direction TB
X3[Ring 3 / 用户态<br/>应用]
X0[Ring 0 / 内核]
XV[VMX root / Hypervisor]
XS[SMM / 固件]
X3 --> X0 --> XV --> XS
end
subgraph ARM[ARMv8-A]
direction TB
A0[EL0 / 用户态]
A1[EL1 / 内核]
A2[EL2 / Hypervisor]
A3[EL3 / Secure Monitor<br/>TrustZone]
A0 --> A1 --> A2 --> A3
end
subgraph RV[RISC-V]
direction TB
RU[U-mode / 用户]
RS[S-mode / 内核]
RH[HS-mode / Hypervisor]
RM[M-mode / 固件]
RU --> RS --> RH --> RM
end
箭头方向是”权限递增”。x86 的 SMM 是”暗层”——OS 无法感知;ARM 的 EL3 与 RISC-V 的 M-mode 是固件层,机密计算和 TrustZone 的信任根都挂在它上面。后面几节围绕这张图展开:页表保护是 ring 0 与 ring 3 之间的执行细则;VMX 是在 ring 0 之上叠加的 hypervisor 层;SEV/TDX 甚至让 ring 0 的 hypervisor 也不可信。
一、特权级:最原始的隔离
1.1 x86 的 ring 0–3
Intel 80286(1982)引入四级特权:
- ring
0:内核模式,可执行特权指令(
hlt、mov cr0、lgdt等),可访问所有内存。 - ring 1 / 2:历史上为”驱动”或”操作系统服务”预留。几乎没有生产 OS 真正用过。
- ring 3:用户模式,特权指令被 CPU 拒绝(#GP,General Protection fault)。
特权级不是一个独立的寄存器,而是 编码在 CS 段选择子的低两位(CPL,Current Privilege Level)。每次段切换或中断都可能触发 CPL 变化。Linux 和 Windows NT 都只用 ring 0 和 ring 3。ring 1、ring 2 在 VMware 二进制翻译时代曾被用来跑 guest 内核,硬件虚拟化成熟后基本退役。
关键限制:CPL 只检查”要不要允许这条指令”,不检查”要不要允许访问这块内存”。访问控制是页表的工作(下一节)。这是为什么 Meltdown 能绕过特权级——它不是通过执行特权指令,而是通过”推测性执行 + cache 侧信道”读取内核地址。
1.2 SMM:比 ring 0 还高的秘密
System Management Mode(SMM)是 Intel 系统管理模式,由固件和 BIOS 使用。它:
- 不可被 OS 关闭
- 拥有独立地址空间(SMRAM)
- 由 System Management Interrupt(SMI)触发
- 对 OS 完全透明
SMM 代码跑在 “ring -2”(常见说法)。它可以访问所有物理内存,OS 几乎无法检测到 SMI 的发生(除非通过 TSC 差值间接推测)。SMM 漏洞(如 2015 年的 BIOS 更新 bug)可以绕过所有 OS 级防护。
OS 对 SMM 的态度:尽量减少 SMI 的发生(延迟敏感系统会要求固件供应商禁用可选 SMI),但无法彻底根除。机密计算(L-108 机密计算)的一个目标就是把 SMM 从 TCB 里踢出去。
1.3 ARMv8 的 EL0–3
ARM 走了不同的路线——Exception Level:
- EL0:用户态
- EL1:内核态(操作系统)
- EL2:hypervisor
- EL3:secure monitor(TrustZone 切换点)
ARMv8 的 EL2 设计原本是 “thin layer for hypervisor”。为了解决 Linux 作为 guest 的性能问题,ARMv8.1 加入了 VHE(Virtualization Host Extensions)和 E2H bit,允许主机 OS 直接跑在 EL2 上,把 guest EL1 跑在 EL1,消除了 Host OS ↔︎ hypervisor 的上下文切换开销。KVM on ARM 就是这么跑的。
EL3 与 TrustZone:EL3 执行 secure monitor,负责在 secure world(TEE)和 normal world(普通 OS)之间切换。Android 的 Keymaster、iOS 的 Secure Enclave 等都是在 TrustZone 里跑。
1.4 RISC-V 的 M/S/U
RISC-V 简洁明了:M(Machine)、S(Supervisor)、U(User)。可选 HS(Hypervisor-extended Supervisor)给虚拟化用。
- M mode:最高权限,固件/BootROM 跑在这里
- S mode:OS 内核
- U mode:用户态
RISC-V 的 PMP(Physical Memory Protection)和 PMA(Physical Memory Attributes)给 M mode 提供了独立于页表的物理内存访问控制——这在嵌入式 RISC-V 场景非常有用(无 MMU 时的保护)。
二、页表保护:真正的内存隔离
特权级不控制内存访问;页表控制。x86_64 的 PTE(Page Table Entry)里有几个关键位:
- P(Present):页是否在内存
- W(Writable):是否可写
- U/S(User/Supervisor):是否允许 ring 3 访问
- NX(No-eXecute):是否禁止执行(AMD 先有,Intel 跟进)
- G(Global):是否在 TLB 中跨地址空间保留
- A/D(Accessed/Dirty):硬件维护的访问/脏位
2.1 U/S 位:区分内核页和用户页
内核页表里,U/S = 0
标记内核私有页;U/S = 1 标记用户可访问页。Ring
3 执行时,CPU 拒绝访问 U/S = 0 的页,发
#PF(Page Fault)。
漏洞:Meltdown(2018)证明了 CPU 在推测性执行时 可以临时读取 U/S = 0 的内核页并把值载入缓存,即使随后的访问检查会回滚指令,cache 状态不回滚。攻击者通过 timing 侧信道读出 cache 差异,反推内核数据。
缓解 KPTI(Kernel Page Table Isolation,2018):给每个进程维护两套页表,用户态模式下的页表里几乎没有内核映射(只保留中断入口、vDSO 等最小必要部分)。这样即使 Meltdown 能读,也无可读。
代价:每次 syscall /
中断进入/退出都要切换 CR3(页表根),增加 TLB miss。Linux 在
Skylake 上实测 open/close 循环延迟增加 15–30%。Intel 后续在
Coffee Lake(2018)硬件修复 Meltdown,KPTI
可关闭(mitigations=off)。
2.2 NX 位:防止数据区代码执行
NX 位(AMD 的 “NX”、Intel 的 “XD”)禁止对应页上的代码被执行。
- 用途:阻止基于栈/堆的代码注入攻击(典型的 buffer overflow 写入 shellcode)
- 激活:CPU 有 NX 支持 + PAE(或 long
mode)+ 内核启用
CONFIG_X86_PAE
NX 不阻止 ROP/JOP(Return-Oriented Programming)——那是 CET 要解决的。
2.3 SMEP / SMAP / PAN
- SMEP(Supervisor Mode Execution
Prevention,Intel Ivy Bridge 2012+):ring 0 时禁止执行
U/S = 1的页。挡的是:攻击者让内核跳到一段用户可控的用户页代码(set_fs(KERNEL_DS)、syscall 后残留 rsp)。 - SMAP(Supervisor Mode Access
Prevention,Haswell 2013+):ring 0 时禁止读写
U/S = 1的页,除非 EFLAGS.AC bit 置位。Linux 的copy_from_user()、copy_to_user()在进入时stac、退出时clac,窗口期允许访问用户页。 - PAN(Privileged Access Never,ARMv8.1):功能等价于 SMAP。
这三项是 2010 年代最重要的内核硬件防护演进。2011 年之前内核经常被 “用户态 pivot” 类攻击得手;有了 SMEP/SMAP 后这类利用难度大幅上升。
三、KASLR:让攻击者找不到目标
KASLR(Kernel Address Space Layout Randomization)在启动时把内核加载到一个随机地址(典型偏移范围 1GB)。目的:让攻击者即使有内核漏洞也不知道要跳到哪里。
弱点:
- 熵太低:x86_64 KASLR 在实际实现上常常只有 9 位熵(512 个可能位置),暴力猜测可行
- 侧信道泄漏:TLB、L1 cache、BTB 都可能泄漏地址;prefetch 指令、侧信道 timing、Meltdown、Spectre 都能打破 KASLR
KASLR 不是根本性防御,是”提高攻击成本”的阶梯。它必须配合其他机制(KPTI、CET、lockdown)使用。
四、投机执行缓解:Spectre / Meltdown 家族
2018 年 1 月 3 日,Jann Horn、Paul Kocher 等人联合披露 Meltdown(CVE-2017-5754)和 Spectre(CVE-2017-5753 / 5715)。这是 OS 安全史上的一个分水岭——在这之前大家觉得 CPU 硬件是可信的。
4.1 Meltdown
利用:推测性越权读取内核内存。
缓解:KPTI。软件层的 page table 隔离。
4.2 Spectre v1(Bounds Check Bypass)
利用:推测性执行越过边界检查。
缓解:
- LFENCE 屏障:关键分支后插入内存屏障
- Array Index Masking:用位掩码而非比较
- Linux 内核用 macro
array_index_nospec()在热点路径上插入
4.3 Spectre v2(Branch Target Injection)
利用:污染 BTB(Branch Target Buffer),让推测性执行跳到攻击者选择的地址。
缓解:
- Retpoline(Google 发明):用
call + ret替代间接跳转,打破 BTB 预测 - IBRS / IBPB / STIBP(Intel 微码):硬件屏障指令
- eIBRS(enhanced IBRS,Ice Lake+):硬件模式,开销更低
4.4 后续变种
Spectre v3a、v4、SSB(Speculative Store Bypass)、L1TF(L1 Terminal Fault)、MDS(Microarchitectural Data Sampling)、ZombieLoad、RIDL、Fallout、TAA、SRBDS、Retbleed、Downfall……
每一种都对应一个微码补丁或内核缓解。Linux 内核在
/sys/devices/system/cpu/vulnerabilities/
下列出了当前机器对每一种漏洞的暴露状态:
$ grep . /sys/devices/system/cpu/vulnerabilities/*
.../meltdown: Mitigation: PTI
.../spectre_v1: Mitigation: usercopy/swapgs barriers and __user pointer sanitization
.../spectre_v2: Mitigation: Retpolines, STIBP: conditional, IBPB: conditional
.../srbds: Mitigation: Microcode
.../tsx_async_abort: Not affected
...
工程影响:这些缓解在某些 workload
上累计性能代价可达
10–30%。生产环境选择性禁用(mitigations=off)是常见但危险的做法。
五、控制流完整性:CET 与 BTI
即使内存执行/写权限分清楚了,攻击者仍可通过 ROP(Return-Oriented Programming)利用合法代码片段组合执行恶意逻辑。Intel CET 和 ARM BTI 是硬件级别的控制流保护。
5.1 Intel CET(Tiger Lake+ / Sapphire Rapids)
两部分:
- SHSTK(Shadow
Stack):硬件维护第二个”影子栈”,每次
call时把返回地址也压入影子栈;ret时比较两个栈上的返回地址,不一致就 #CP。 - IBT(Indirect Branch
Tracking):间接跳转目标必须是
ENDBR32/64指令,否则触发 fault。
Linux 6.6+ 在支持的 CPU 上可启用 user space CET(glibc
2.28+ 编译时 -fcf-protection)。内核内 CET
支持在持续推进。
5.2 ARM BTI / PAC
- BTI(Branch Target Identification,ARMv8.5):类似 IBT,间接跳转目标必须是 BTI 指令
- PAC(Pointer Authentication Code,ARMv8.3):把指针的高位编码 HMAC,解指针时验证;指针被篡改即失败
PAC 比 CET SHSTK 更精细——它保护任意指针(包括 C++ vtable、函数指针),不只是返回地址。iOS 的 PAC 使用是 PAC 在消费级的最大规模部署。
六、内存标记:MTE
MTE(Memory Tagging Extension,ARMv8.5)给每 16 字节内存分配一个 4-bit 标签,指针的高位也带标签;硬件在访问时比对标签。
用途:检测 use-after-free 和 buffer overflow。
模式:
- Sync mode:不匹配立即 trap(性能影响明显,用于开发/测试)
- Async mode:不匹配异步报告(性能开销 < 5%,适合生产)
Android 从 Pixel 8(2023)开始在内核和应用态广泛启用 MTE。它被认为是”内存安全的硬件补丁”——对于无法用 Rust 重写的 C 代码是有效止损。
七、PKU / PKRU:进程内权限分区
PKU(Protection Keys for Userspace,Skylake-X 2016+)允许同一地址空间内的不同页被打上 key(0–15),每个线程的 PKRU 寄存器控制哪些 key 可读/可写。
典型用途:
- 浏览器把 JIT 编译出的代码页标为 key A,JIT runtime 写入前切 PKRU 允许写 key A,写完后再切回只读——防 exploit 直接改 JIT 代码。
- 数据库把敏感数据页标为 key B,只有特定操作序列能读取。
与 SMAP 区别:SMAP 是内核/用户分界;PKU 是进程内分区。两者独立。
内核内也有 PKS(Protection Keys for Supervisor,Icelake+)做内核内部页权限分区,但目前 Linux 使用很少。
八、地址空间隔离的硬件辅助:ASID、PCID、VPID
让 TLB 不跨地址空间失效,是降低 KPTI / 虚拟化切换开销的关键。
- PCID(Process Context ID,x86):每个页表根关联一个 12-bit PCID;TLB 条目携带 PCID,切换 CR3 不必 flush。
- ASID(Address Space ID,ARM):ARMv8 的等价机制,8 或 16 bit。
- VPID(Virtual Processor ID,VMX):区分不同虚机的 TLB,避免 VM exit/entry 的全 flush。
- INVPCID / INVLPGB:精准失效指令,INVLPGB(AMD Zen 3+)可广播到其他 CPU,加速 TLB shootdown(D-32 会展开)。
九、VMX / SVM:硬件虚拟化
Intel VMX(VT-x)和 AMD SVM 把”运行 guest”变成硬件特性:
- CPU 有两种模式:VMX root(hypervisor)和 VMX non-root(guest)
- 特定事件(MSR 写、I/O、特定 MSR 读)触发 VM-exit,把控制权交回 hypervisor
- EPT / NPT(Extended / Nested Page Tables):第二层页表,guest 页表映射到 host 页表,避免 shadow page table 的维护开销
- VMCS(Virtual Machine Control Structure):guest 状态与 exit 原因
性能优化:
- APIC-v:虚拟化中断直投给 guest,不用每次 VM-exit
- Posted Interrupts:从 host 驱动直接投中断到 guest 而不需经过 hypervisor
- VM Functions (VMFUNC):从 guest 态直接切换 EPT 页表集(不用 exit)
这些优化让 KVM 在网络和 I/O 密集场景的开销降到 10% 以内。L-101、L-102 会详细展开。
十、机密计算:SEV / TDX / CCA
传统虚拟化下,hypervisor 可读所有 guest 内存——这对云厂商自己想做 “即使云运营者也不能偷看客户数据” 是过不去的。机密计算(Confidential Computing)通过硬件加密 + attestation 解决:
- Intel SGX(Skylake 2015+):应用级 enclave,页粒度加密。问题:被反复发现侧信道漏洞;SGX1 容量只有 128MB;Intel 在 12th Gen 消费级 CPU 上 deprecated。
- AMD SEV / SEV-ES / SEV-SNP:VM 级加密,SEV-SNP 还提供 integrity。Memory encryption key 每个 guest 独立;hypervisor 无法读。
- Intel TDX(Sapphire Rapids 2023+):类似 SEV-SNP,VM 粒度;引入 TD(Trust Domain)概念。
- ARM CCA(Confidential Compute Architecture):realm 概念,EL3/EL2 里跑 RMM(Realm Management Monitor)。
机密计算带来的 OS 设计影响:
- Hypervisor 不再可信,必须最小化
- I/O 路径需要 “swiotlb” 或 secured DMA(加密边界在 CPU 内部 vs PCIe 边界)
- Measurement/attestation 成为必要流程
- OS 自己要适配(Linux 有
coco/子系统专门处理机密 guest)
M-108 会细讲。
十一、小结:深度防御的层次表
现代系统把所有这些机制叠起来:
目的
ring 0/3 基础特权分离
U/S, W, NX (页表) 细粒度内存权限
SMEP / SMAP / PAN 禁止内核执行/访问用户页
NX + DEP 阻止数据区执行
KASLR 随机化减少攻击确定性
KPTI 隔离内核与用户页表(对抗 Meltdown)
Retpoline / IBRS / eIBRS 对抗 Spectre v2
LFENCE / array_index_nospec 对抗 Spectre v1
CET (SHSTK + IBT) 阻止 ROP/JOP
BTI / PAC ARM 的 CFI + 指针认证
MTE 检测 UAF / overflow
PKU / PKRU 进程内权限分区
PCID / ASID / VPID 减少 TLB flush 开销
VMX / SVM + EPT/NPT 虚拟化隔离
SEV / TDX / CCA 机密计算(不信 hypervisor)
TrustZone / SMM 专门的高特权环境
没有任何一项是万能的。KPTI 挡不住
Spectre;NX 挡不住 ROP;CET 挡不住类型混淆;MTE
有假阴性;机密计算的 attestation
有供应链信任问题。这是为什么现代内核的 arch/
目录里 “hardware mitigations”
的代码量在过去十年膨胀了数倍——每一个新漏洞都留下一段新代码。
对你设计/审阅系统的意义:
- 明确你假设的 TCB 边界(到 OS?到 hypervisor?到 CPU 微码?到固件?)
- 明确你对每一层威胁的覆盖(是否暴露在物理攻击?是否假设邻居虚机可信?)
- 不要以为”打开所有 mitigation 就安全了”——你要知道它们挡什么、漏什么
下一篇 A-05 系统调用 ABI 进入 OS 与应用的接触面——当用户代码要请求内核做事,这个跨特权级的跳跃在各架构是如何实现的。
参考文献
- Intel. Intel 64 and IA-32 Architectures Software Developer’s Manual. Volumes 3A, 3B, 3C(特权、内存管理、VMX).
- AMD. AMD64 Architecture Programmer’s Manual. Volumes 2, 3(系统编程、一般用途指令).
- ARM Ltd. Arm Architecture Reference Manual for A-profile Architecture. DDI 0487.
- Lipp, M., et al. “Meltdown: Reading Kernel Memory from User Space.” USENIX Security, 2018.
- Kocher, P., et al. “Spectre Attacks: Exploiting Speculative Execution.” S&P, 2019.
- Canella, C., et al. “A Systematic Evaluation of Transient Execution Attacks and Defenses.” USENIX Security, 2019.
- Intel. “Control-flow Enforcement Technology Specification.” 2019.
- ARM. “Pointer Authentication on ARMv8.3.” White paper, 2017.
- AMD. “AMD SEV-SNP: Strengthening VM Isolation with Integrity Protection and More.” White paper, 2020.
- Intel. “Intel Trust Domain Extensions (TDX) Whitepaper.” 2021.
- Serebryany, K. “ARM Memory Tagging Extension and How It Improves C/C++ Memory Safety.” USENIX ;login:, 2019.
工具与源码
- Linux
arch/x86/mm/、arch/arm64/mm/—— 页表与 MMU - Linux
arch/x86/kernel/cpu/bugs.c—— CPU 漏洞缓解主入口 tools/arch/x86/lib/—— KPTI、retpoline 相关汇编/sys/devices/system/cpu/vulnerabilities/—— 运行时查询dmesg | grep -i mitigation—— 启动时的缓解激活日志
上一篇:宏内核 vs 微内核 下一篇:系统调用 ABI
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【操作系统百科】KASLR 与内核缓解措施
Spectre/Meltdown 时代留给内核的性能税有多重?KASLR、KPTI、retpoline、IBRS/eIBRS、RSB stuffing、SSBD——本文讲 CPU 漏洞缓解措施的内核实现。
【操作系统百科】ARMv8 VMSA 页表
ARMv8-A 翻译体制与 x86 差异很大:两套 TTBR、可选 4K/16K/64K granule、ASID 原生标签、nG/G 分离。本文梳理 VMSAv8-64 核心:TTBR0/1、granule、descriptor、ASID、VHE、MTE、BTI。
【操作系统百科】内存回收
Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。
【操作系统百科】交换
swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。