1. 导言

性能测试对于 Linux 发行版来说至关重要,Alibaba Cloud Linux 2 也是如此。(Alibaba Cloud Linux 2 是阿里巴巴操作系统团队推出的一款开源且免费的 Linux 操作系统发行版,其深度集成与优化阿里云基础设施,旨在为阿里云 ECS 客户提供丰富功能、高性能且稳定的操作系统服务,欢迎大家使用。)

然而在测试过程中发现很多子系统例如网络子系统的性能与 CPU 调度性能密切相关。系统的调度性能固然与内核中的调度算法相关,然而过去一段时间内现代 CPU 架构下不断发现的硬件漏洞及其修复严重影响了系统的调度性能。因而了解这些 CPU 漏洞的原理及修复,对于系统性能测试具有重要意义。

本文尝试对当前版本内核中存在的 CPU 漏洞及修复作一个简单的介绍,本文亦可作为一个知识库,在需要的时候快速索引浏览。由于作者水平以及文章篇幅所限,文中若存在错误,请大家共同交流学习 ^^ 。

2. 背景介绍

2018年一月,Google Project Zero 爆出现代处理器存在安全漏洞 Spectre 与 Meltdown。其实早在 2017 年Google Project Zero 就已经发现了这些漏洞,而与此同时 Moritz LippPaul Kocher 等安全研究人员也对此进行了研究。

攻击者可以使用这些漏洞窃取高特权级的数据,因而对系统安全存在严重威胁。同时这两组漏洞几乎涉及当今大部分主流的处理器(包括 Intel、AMD、ARM 等多种架构),因而一公开便引起了广泛的讨论。包括 Linux 在内的主流操作系统随后都对漏洞进行了相应的修复。由于这些漏洞利用处理器硬件的投机执行(speculative execution)以及乱序执行(out-of-order execution)特性,而这些特性对于现代处理器的性能提升具有不可或缺的作用,因而其中的一些修复会带来较大的性能回退。

由于这些漏洞源自现代处理器硬件的架构设计,软件方面的修复通常只能缓解而不能根治问题,同时自 2018年一月 Spectre 与 Meltdown 漏洞首次公布以来,新变种以及新类型的漏洞不断出现,因而可以预见这些漏洞的存在在未来相当一段时间内会成为常态。

本文描述了当前 CPU 架构下存在的漏洞,对于各个漏洞现有的修复方案以及开启方式。

/sys/devices/system/cpu/vulnerabilities/目录下存在以下文件,分别描述对应的 CPU 漏洞:

  • meltdown
  • spectre_v1
  • spectre_v2
  • spec_store_bypass
  • l1tf
  • mds

这些文件的输出格式为

  • “Not affected” 表示当前 CPU 不存在该漏洞
  •  ”Vulnerable” 表示当前 CPU 存在该漏洞,同时没有采取任何缓解措施
  • “Mitigation: $M” 表示当前 CPU 存在该漏洞,同时采取了相应缓解措施

3. 漏洞详解

3.1 Spectre Variant 1

本节描述的 spectre variant 1 特指 Bounds check bypass,SWAPGS 见下一节。

/sys/devices/system/cpu/vulnerabilities/spectre_v1 描述 Spectre variant 1 的修复情况。

早期版本中 Spectre Variant 1 只存在对于 array bounds check bypass 的修复,且这种修复无法关闭,此时 spectre_v1 文件的输出只有一种显示,即:

  • “Mitigation: __user pointer sanitization”

而在之后 spectre_v1 增加了对 swapgs 的修复,详情见下一节。

3.1.1 Array bounds check bypass

Spectre variant 1 (CVE-2017-5753, Bounds check bypass) 的原理是利用处理器在执行条件分支(conditional branch)时的投机执行(speculative execution),使得处理器在投机执行 false 分支的时候泄露相关的旁路信息,使得攻击者通过旁路攻击窃取数据。

Spectre variant 1 的攻击方式多见于 array bounds / user pointer check bypass。内核对于该攻击方式已经存在相应修复:对于前者,在使用 array index 访问内存之前,将 array index 执行 mask 操作,从而确保 index 落在 [0, array_size] 的有效范围内;而对于后者,在对 user pointer 执行有效性检查的时候,添加一条 lfence 指令,以防止检查完成前投机执行之后的指令。

以上这些修复的指令开销很小,同时只有在 1) 执行数组访问,同时 array index 是用户传入的值,例如系统调用,或 2) 执行 copy-from-user 的时候显式调用对应的修复,而不是全局开启,因而开销较小;这些修复在 Upstream v4.16-rc2 版本合入。

3.1.2 开关

对于 array bounds check bypass 的修复目前无法关闭。

3.2 SWAPGS

SWAPGS 是 spectre variant 1 的另一个变种,此时 /sys/devices/system/cpu/vulnerabilities/spectre_v1 文件的输出有:

  • “Vulnerable: __user pointer sanitization and usercopy barriers only; no swapgs barriers”

表示开启对 array bounds check bypass 的修复,关闭对 swapgs 的修复

  • “Mitigation: usercopy/swapgs barriers and __user pointer sanitization”

表示开启所有 spectre variant 1 修复,包括对 array bounds check bypass 的修复,以及对 swapgs 的修复。

3.2.1 SWAPGS

Spectre variant 1 的原理是利用处理器执行条件分支(conditional branch)时的投机执行,因而其攻击方式不局限于 array bounds / user pointer check bypass,另一种攻击方式是在中断或异常发生时,攻击者可以训练 branch predictor,使其错误地跳过或执行 swapgs 指令,从而为旁路攻击制造条件,这种攻击方式也就被称为 swapgs

例如当由用户态进入中断或异常时,以下代码中在条件分支判断结束前,CPU 就可能会跳过 swapgs 而执行之后的代码,此时执行 GS 寄存器的访问操作时,由于跳过了 swapgs 操作,因而此时实际访问的仍是用户态 GS 寄存器,此时攻击者可以精心设计用户态 GS 寄存器的值,以获取特定内存地址处内存的值。

if (coming from user space)
		swapgs
mov %gs:<percpu_offset>, %reg1

对于该攻击方式的修复也是在中断或异常的入口,在条件分支之后添加 lfence 指令,该修复在 Upstream v5.3-rc4  合入主线。

3.2.2 开关

可以通过 nospectre_v1=off 或 mitigations=off 启动参数关闭对 swapgs 的修复,注意这两个参数均不能关闭之前对 array bounds check bypass 的修复。

3.3 Spectre Variant 2

/sys/devices/system/cpu/vulnerabilities/spectre_v2 描述 Spectre Variant 2 的修复情况,其输出有如下情形:

  • “Vulnerable”,表示未开启任何修复
  • “Mitigation: Full generic retpoline”,表示当前开启 retpoline 修复
  • “Mitigation: Full AMD retpoline”,表示当前开启 AMD 处理器专用的 retpoline 修复,只有 AMD 处理器可以开启该修复
  • “Mitigation: Enhanced IBRS”,表示当前开启 IBRS 修复

3.3.1 原理

Spectre variant 2 (CVE-2017-5715, Branch target injection) 实际是利用了处理器执行间接跳转指令时的投机执行行为。

间接跳转指令执行过程中,当需要跳转的绝对地址不在缓存中、而需要从内存读取时,就会执行分支预测功能。处理器硬件内部使用 BTB (Branch Target Buffer) 来缓存 (间接跳转指令的原地址, 跳转指令的目标地址) 这一对数据,处理器硬件的分支预测即使用 BTB 来预测当前执行的间接跳转指令对应的目标跳转地址。

然而该机制存在的一个问题是,同一个处理器上的不同应用程序会共用同一个 BTB,因而 spectre variant 2 的原理即是攻击者通过用户态程序执行特定的间接跳转指令来训练当前处理器的 BTB,从而使同一处理器上运行的 Linux 内核运行间接跳转指令时,分支预测功能就会被误导跳转到攻击者设计的一个特定地址上,从而运行攻击者设计的程序。

3.3.2 retpoline 修复

spectre variant 2 漏洞主要攻击间接跳转指令,Google 提出的一种软件解决方案称为 retpoline,其原理是使用 ret 指令来实现地址跳转。由于 ret 指令使用的 RSB (Return Stack Buffer) 预测机制更为明确,因而不会受到攻击者的恶意训练。该修复在 Upstream v4.15-rc8 版本合入。

3.3.3 IBRS 修复

retpoline 的原理是使用 RSB ,从而规避用户态程序对 BTB 的恶意训练。然而对于 Skylake 及之后的机型,retpoline 并不能完全解决 Spectre variant 2。这是因为 Skylake 及之后的机型在调用深度较大而导致 RSB 用尽时,会“回退”使用 BTB,从而又重新遭受 Spectre 威胁。

Intel 提出的一种称为 IBRS (Indirect Branch Restricted Speculation) 的解决方案,其原理是运行于高特权级(privilege level) 的程序,不能复用低特权级程序缓存的 BTB,即内核在使用 BTB 进行分支预测时,不能使用用户态程序训练的 BTB 项。该解决方案需要处理器的 microcode 更新支持。

该修复方案中处理器每次由低特权级切换到高特权级时,都需要软件配置一次相应的寄存器,以 flush 掉之前低特权级程序训练的 BTB,因而实际存在一定的性能损耗。IBRS 修复方案实际没有合入 Upstream,因而也不存在与 Cloud Kernel。

3.3.4 EIBRS 修复

之前描述的 IBRS 修复需要处理器每次由低特权级切换到高特权级时,软件都需要配置一次相应的寄存器,这给软件设计带来不便,同时存在一定的性能损耗。

EIBRS (Enhanced IBRS) 是一种改进的 IBRS,其原理与 IBRS 相同,唯一的区别是只需要在系统初始化时对寄存器进行一次设置,之后处理器由低特权级切换到高特权级时,处理器硬件都会自动地 flush 掉之前低特权级程序训练的 BTB。该修复方案需要处理器硬件支持,目前只支持 “future CPUs”,在 Upstream v4.19-rc1 合入。

3.3.5 开关

可以使用 spectre_v2 启动参数可以设置是否开启 Spectre variant 2 修复,以及选择哪一种修复方案,其格式为:

spectre_v2=[off|on|retpoline|retpoline,amd|retpoline,generic|auto]
  • “off”, 表示关闭 Spectre variant 2 修复;
  • “retpoline,generic”, 表示开启 retpoline 修复;
  • “retpoline,amd”, 表示开启 AMD 处理器特定的 retpoline 修复;
  • “retpoline”,表示开启 retpoline 修复,但是会根据当前处理器的型号,自定选择 “retpoline,generic” 或是 “retpoline,amd”;
  • “on”“auto” 具有相同的效果,表示开启 Spectre variant 2 修复,并自动选择修复方案:若处理器支持 EIBRS ,则开启 EIBRS 修复,否则开启 retpoline 修复。

当未指定 spectre_v2 启动参数时,默认为 spectre_v2=auto,即自动选择 Spectre variant 2 的修复方案。

需要关闭 Spectre variant 2 修复时,可以通过 nospectre_v2 或 spectre_v2=off 启动参数关闭

从 Upstream LTS v4.19.43  版本起,也可以使用 mitigations=off 启动参数关闭包含 Spectre Variant 2 修复在内的所有修复。

3.4 Spectre Variant 4 (Speculative Store Bypass)

/sys/devices/system/cpu/vulnerabilities/spec_store_bypass 描述 Speculative Store Bypass 的修复情况,其输出有如下情形:

  • “Vulnerable”,表示不开启任何 Speculative Store Bypass 修复
  • “Mitigation: Speculative Store Bypass disabled”,表示在处理器硬件层面全局关闭 store buffer bypass 特性,这会较大程度地影响处理器性能
  • “Mitigation: Speculative Store Bypass disabled via prctl”,表示用户态程序可以通过 prctl 系统调用修复 Speculative Store Bypass
  • “Mitigation: Speculative Store Bypass disabled via prctl and seccomp”,表示用户态程序可以通过 seccom 框架修复 Speculative Store Bypass

3.4.1 原理

Spectre variant 4 (CVE-2018-3639, Speculative Store Bypass) 利用 store buffer bypass 时泄漏的旁路信息。

现代处理器在对内存进行读写时,通常在处理器与内存之间维护一个高速缓存,称为 load buffer 与 store buffer。当处理器对某个内存地址进行读操作时,除了查询 load buffer,还需要查询 store buffer,以获取处理器之前对该内存地址写入的值。尽管 store buffer 相对于内存属于高速缓存,然而其访问速度相对于 CPU 来说仍然较慢。因而为了提升性能,在这种情况下现代处理器通常采用 Speculative Store Bypass 的优化方式,即假设 store buffer 中不存在当前内存地址的更新值,就开始投机执行之后的指令,若之后发现 store buffer 中存在更新的值,就丢弃之前投机之行的结果。然而在该投机执行的过程中,已经泄露了相关的旁路信息。

3.4.2 Speculative Store Bypass Disable (SSBD) 修复

可以通过设置处理器的相关寄存器,全局关闭处理器的 Speculative Store Bypass 优化。该修复方案需要 microcode 更新支持,Upstream v4.17-rc7 合入。

3.4.3 prctl 修复

Speculative Store Bypass 攻击只能发生在相同特权级下,即用户态无法攻击内核态,因而 Spectre variant 4 常见的一种攻击场景是 sandbox。这种场景下同一个进程分别运行 sandbox 主体程序、以及运行在 sandbox 内部的 untrusted 程序这两种程序,通过 Spectre variant 4 运行在 sandbox 内部的程序有可能窃取 sandbox 主体程序的数据。

同时之前所述全局关闭 Speculative Store Bypass 的方式代价过大,内核提供了一种 prctl 的修复方案。这种修复方案实际是以 per-thread 粒度关闭 Speculative Store Bypass 优化。用户态进程可以调用 prctl 系统调用(with PR_SET_SPECULATION_CTRL - PR_SPEC_DISABLE 参数),使得处理器只有在调度执行当前进程的过程中,关闭 Speculative Store Bypass 优化。该修复方案在 Upstream v4.17-rc7 合入。

3.4.4 seccomp 修复

与 prctl 修复方案类似,seccomp 修复也是以 per-thread 粒度关闭 Speculative Store Bypass 优化,只是采用 seccomp 框架的进程会自动关闭该优化,而不需要进程显式调用 prctl 系统调用。该修复方案在 Upstream v4.17-rc7 合入。

3.4.5 开关

spec_store_bypass_disable 启动参数用于设置是否开启 Speculative Store Bypass 修复,以及采用何种修复方案,其格式为:

spec_store_bypass_disable=[off|on|auto|prctl|seccomp]
  • “off”,表示不开启任何修复
  • “on”,表示全局关闭处理器的 Speculative Store Bypass 优化
  • “prctl”,表示采用 prctl 修复方式
  • “seccomp”,表示采用 seccomp 修复方式
  • “auto”,表示自动选择修复方式,若系统支持 seccomp 框架,则默认采用 seccomp 修复方式,否则采用 prctl 修复方式

当未指定 spec_store_bypass_disable 启动参数时,若处理器支持 Speculative Store Bypass Disable,则默认采用spec_store_bypass_disable=auto,否则默认不开启所有 Speculative Store Bypass 修复。

可以通过 spec_store_bypass_disable=off 或 nospec_store_bypass_disable 启动参数关闭该修复。以上修复以及启动参数都在 Upstream v4.17-rc7 版本合入。

从 Upstream LTS v4.19.43  版本起,也可以使用 mitigations=off 启动参数关闭包含 Speculative Store Bypass 修复在内的所有修复。

3.5 Meltdown

/sys/devices/system/cpu/vulnerabilities/meltdown  描述 Meltdown 的修复情况,其输出

  • “Vulnerable”,表示未开启任何修复
  • “Mitigation: PTI”,表示采用 PTI 修复

3.5.1 原理

现代操作系统通常将内核态与用户态的地址空间相分隔,用户态程序没有权限访问内核态的地址空间,这一特性是系统安全的重要基石。

Meltdown (CVE-2017-5754) 攻击则利用现代处理器的乱序执行(out-of-order execution)特性,打破了用户态、内核态地址空间之间的隔离,通过旁路攻击,使得用户态程序可以获取内核态地址空间处内存的值。

movzx (%rcx), %rax
shl $12, %rax
movq (%rbx, %rax), %rbi

考虑以上示例代码,假设 rcx 寄存器保存内核地址空间内需要探测的某一内存地址,指令 1 即 movzx 指令表示读取该内存地址处内存的值,并保存到 rax 寄存器中。在该指令执行过程中检测到进程不具备该内存地址的访问权限,因而会触发异常,而导致 rax 寄存器中的值被丢弃。

以上过程都符合处理器的设计,然而实际上处理器硬件自身存在指令乱序执行的优化,在执行 movzx 指令尚未结束的情况下,之后的指令 2、3 实际已经开始运行。在指令 1 (权限检查)结束之前,指令 2、3 已经可以访问 rax 寄存器的值。虽然之后指令 1 结束时,指令 2、3 之行过程中寄存器的状态都被丢弃,但是 cache 的状态变化得以保留。攻击程序通过 cache 旁路攻击就可以获取泄露的内核地址空间中内存的值。

3.5.2 PTI 修复

以上 Meltdown 攻击实现的另外一个重要条件是,Linux 内核在实现时出于性能考虑,用户态进程使用的 page table 实际包含内核态地址空间的映射,因而在以上攻击方式中,攻击者可以在用户态进程中获取内核态地址空间的内存数据。

KPTI (Kernel Page Table Isolation) 则恰好可以缩减用户态进程使用的 page table 中内核地址空间的映射,其原理是进程运行在用户态时,将内核映射中除 exception entry 之外的其他映射都设置为无效,这样再发生 meltdown 攻击时,由于对应的映射无效,因而攻击者已经无法再读取对应内核地址空间中的数据。当进程通过系统调用或异常由用户态进入内核态时,会将用户进程的 page table 中的内核映射切换为有效的映射;当调用结束进程从内核态回到用户态时,再次切换进程的内核映射,使其变为无效。

KPTI 其实早在 Meltdown 漏洞爆发之前就已经出现,因为恰好可以缓解 Meltdown 攻击而被广泛使用,其于 Upstream v4.15 合入。

KPTI 修复对于系统性能存在较大影响,可以参考 Brendan Gregg 的分析。

3.5.3 开关

pti 启动参数(Upstream v4.15-rc6 合入)用于设置是否开启 KPTI 修复,其格式为

pti=[off|on|auto]
  • “off”,表示不开启 KPTI 修复
  • “on”,表示开启 KPTI 修复
  • “auto”,表示只有当前处理器存在 Meltdown 漏洞时才开启 KPTI 修复

当未指定 pti 启动参数时,默认使用 “pti=autoi” 配置

可以通过 pti=off 或 nopti (Upstream v4.15-rc6 合入)启动参数关闭 KPTI 修复。

从 Upstream LTS v4.19.43  版本起,也可以使用 mitigations=off 启动参数关闭包含 KPTI 修复在内的所有修复。

3.6 L1TF

/sys/devices/system/cpu/vulnerabilities/l1tf 描述 L1TF 的修复情况,其输出有如下格式:


Mitigation: PTE Inversion;[VMX: ][, SMT: ]
  • “Mitigation: PTE Inversion”,表示使用 PTE inversion 修复
  • VMX 字段描述是否开启 L1D flush 修复
    • “vulnerable”,表示不开启 L1D flush 修复
    • “conditional cache flushes”,表示开启 conditional L1D flush 修复
    • “cache flushes”,表示开启 unconditional L1D flush 修复,
  • SMT 字段描述是否开启 SMT
    • “vulnerable”,表示开启 SMT
    • “disabled”,表示关闭 SMT

3.6.1 原理

L1TF (CVE-2018-3615,  L1 data Terminal Fault) 同样是利用处理器的投机执行来获取一个 physical page 的内容。

Linux 中使用 page table entry (PTE) 来实现虚拟地址到物理地址之间的转换,x86 PTE 的格式如上图所示,其中 PFN (Page Frame Number) 字段描述对应 page frame 的物理地址,P (Present) 字段描述当前虚拟地址是否存在对应的物理地址,即是否为该虚拟地址分配了对应的 physical page frame。进程在使用虚拟地址访问内存时,会首先找到该虚拟地址对应的 PTE,若 P 字段为 0,则会发生 page fault;若 P 字段为 1,根据 PFN 字段的值在 L1 data cache 中寻找是否存在缓存。

Intel 处理器在判断 P 标志位是否为 1 的时候,在判断尚未结束之前会投机之行之后的代码,即根据 PFN 字段的值在 L1 data cache 中寻找是否存在缓存。若缓存命中,那么通过 cache 旁路攻击,攻击者就可以获取某一物理地址处的内存数据。

3.6.2 PTE inversion 修复

当不涉及虚拟化时,L1TF 的危害其实相对有限,因为攻击者不太容易构造 PFN 字段具有特定值的 PTE,这样攻击者就不能通过 L1TF 获取特定物理地址处的内存值。

即使攻击方式不太容易实现,数据泄露的风险是确实存在的。同时考虑到以上攻击方式成功的重要条件是 PFN 构成的物理地址在 L1 cache 中缓存命中,因而 PTE inversion 可以用于修复。其原理是当开启 PTE inversion 时,逆序存储 non-Present 的 PTE 中的所有 bit,这样以上攻击方式中,使用 PFN 字段逆序之后的值在 L1 cache 中就会发生 cache miss。

PTE inversion 总是开启。

3.6.3 L1D flush 修复

注意:该修复只适用于 host kernel

L1TF 攻击也可以发生在 guest VM 中,此时若攻击者可以自由更换 guest kernel,那么攻击者就可以自由地构造 PTE 使得 non-Present PTE 的 PFN 字段具有特定值,从而读取任意物理地址处的内存值,使得 guest VM 获取 host kernel 甚至其他 guest VM 的数据。

guest kernel 使用 PTE inversion 只能防止用户态进程窃取 guest kernel 的数据,而为了防止 guest VM 获取 host 乃至其他 guest VM 的数据,host kernel 可以采用 L1D flush 的修复方式。其原理是,考虑到 L1TF 攻击方式的重要条件是对应的物理地址在 L1 data cache 中存在缓存,那么 host kernel 每次在进入 guest 之前,都执行 flush L1 data cache 操作。

当 VMEXIT/VMENTER 的频率较大时,该修复方式会对系统带来较大的性能回退。因而 L1D flush 实际提供两种工作模式:

  • conditional flush
  • unconditional flush

unconditional flush 是指每次 VMENTER 都执行 flush L1 data cache 操作,性能开销大,但是相对更安全;
conditional flush 是指当 VMEXIT 与 VMENTER 之间执行的都是不重要的代码路径时,就不执行 flush L1 data cache 操作,这减小了性能开销,但是会泄露 hypervisor 的内存布局。

3.6.3 SMT Disabling 修复

注意:该修复只适用于 host kernel

以上 L1D flush 修复可以防止 guest VM 对 host kernel 的 L1TF 攻击,但是在开启 SMT (Symmetric Multi-Threading, or Hyperthreads) 的情况下,一个 logical CPU 执行 L1D flush 操作后,同一个 Core 上的另一个 logical CPU 实际可以重新生成 L1D cache。

因而为了让 L1D flush 修复真正生效,有时还需要配合关闭 SMT 特性。

3.6.4 开关

l1tf 启动参数用于设置是否开启 L1TF 修复,以及采用何种修复方案,其格式为:

l1tf=[off|flush,nowarn|flush|flush,nosmt|full|full,force]
  • “off”,表示不开启任何 L1TF 修复
  • “flush”,表示开启 conditional L1D flush 修复,关闭SMT Disabling 修复
  • “flush,nowarn”,与 “flush” 一样,开启L1D flush 修复,关闭SMT Disabling 修复,只是 “flush” 在第一台 VM 启动时会发出 warning 警告(因为 SMT Disabling 修复没有开启而可能存在潜在的威胁),而 ”flush,nowarn” 则不会
  • “flush,nosmt”,表示开启 conditional L1D flush 修复,开启 SMT Disabling 修复
  • “full”,表示开启 unconditional L1D flush 修复,开启 SMT Disabling 修复
  • “full,force”,与 “full” 一样,只是 ”full” 配置下还可以通过 sysfs 接口在运行时动态开启或关闭 L1D flush 修复或 SMT Disabling 修复,而 ”full,force” 配置下则不行

可以通过 l1tf=off ( v4.19-rc1 合入)关闭 L1TF 修复。

从 Upstream LTS v4.19.43 版本起,也可以使用 mitigations=off 启动参数关闭包含 L1TF 修复在内的所有修复。

3.7 MDS

/sys/devices/system/cpu/vulnerabilities/mds  ( v4.19.43 合入)描述 MDS 的修复情况

  • “Vulnerable”,表示不开启 MDS 修复
  • “Vulnerable: Clear CPU buffers attempted, no microcode”,表示开启 CPU buffer clear 修复,但是当前处理器没有 microcode 支持,因而当前修复基于 best effort 原则
  • “Mitigation: Clear CPU buffers”,表示开启 CPU buffer clear 修复

3.7.1 原理

MDS (Microarchitectural Data Sampling) 是利用处理器的投机执行,通过旁路攻击获取 store buffer、fill buffer、load port 中数据的攻击方式。

通过 MDS 攻击,低特权级程序可以获取高特权级的数据,即用户态程序可以获取内核数据,guest kernel 可以获取 host 数据,但是由于攻击程序无法构造特定的内存地址以获取特定地址处的内存数据,因而只能通过“采样”的方式获取某一内存地址处对应的数据,同时由于这些缓存单次泄漏的数据量相对较小,攻击者需要收集大量数据才有可能推测敏感数据,因而其危害相对有限。

针对 MDS 的修复主要是由内核态切换到用户态,或由 hypervisor 切换到 guest 时,对 store buffer、fill buffer、load port 等缓存执行 flush 操作,该修复需要 microcode 更新支持。当处理器支持 SMT 时,该修复还需要配合关闭 SMT,以防止同一个 physical core 上的另一个 logical CPU 重新填充这些缓存。

3.7.2 开关

可以通过 mds=[off|full|full,nosmt] (v4.19.43 合入) 启动参数控制知否开启 MDS 修复

  • “off”,表示不开启 MDS 修复
  • “full”,表示开启 CPU buffer clear 修复,但是不会关闭 SMT
  • “full,nosmt”,表示开启 CPU buffer clear 修复,同时关闭 SMT

可以使用 mds=off (v4.19.43 合入) 启动参数关闭 MDS 修复。

从 Upstream LTS v4.19.43  版本起,也可以使用 mitigations=off 启动参数关闭包含 MDS 修复在内的所有修复。

4. 外部链接

Spectre Attacks: Exploiting Speculative Execution
Meltdown: Reading Kernel Memory from User Space
Spectre Side Channels
Deep Dive: Indirect Branch Restricted Speculation
Speculative-Execution-Side-Channel-Mitigations
Retpoline: A Branch Target Injection Mitigation
Speculative Store Bypass
Speculative Store Bypass explained: what it is, how it works 
Meltdown strikes back: the L1 terminal fault vulnerability
L1TF - L1 Terminal Fault
Meltdown strikes back: the L1 terminal fault vulnerability
MDS - Microarchitectural Data Sampling
Deep Dive: Intel Analysis of Microarchitectural Data Sampling