L1TF - L1 终端故障

L1 终端故障是一种硬件漏洞,当用于访问的虚拟地址的页表项的 Present 位被清除或其他保留位被设置时,允许非特权推测性访问 L1 数据缓存中可用的数据。

受影响的处理器

此漏洞影响范围广泛的 Intel 处理器。该漏洞不存在于

  • 来自 AMD、Centaur 和其他非 Intel 供应商的处理器

  • CPU 系列 < 6 的较旧处理器型号

  • 一系列 Intel ATOM 处理器(Cedarview、Cloverview、Lincroft、Penwell、Pineview、Silvermont、Airmont、Merrifield)

  • Intel XEON PHI 系列

  • IA32_ARCH_CAPABILITIES MSR 中设置了 ARCH_CAP_RDCL_NO 位的 Intel 处理器。如果设置了该位,则 CPU 也不受 Meltdown 漏洞的影响。这些 CPU 应在 2018 年底上市。

是否受处理器影响可以从 sysfs 中的 L1TF 漏洞文件中读取。请参阅 L1TF 系统信息

问题

如果指令访问相关页表项 (PTE) 的 Present 位被清除或其他保留位被设置的虚拟地址,则推测执行会忽略无效的 PTE,如果引用的数据存在于 L1 数据缓存中,则会加载该数据,就好像 PTE 中地址位引用的页面仍然存在且可访问一样。

虽然这是一种纯粹的推测机制,并且该指令最终在退出时会引发页面错误,但加载数据并使其可用于其他推测指令的纯粹行为,为非特权恶意代码打开了侧信道攻击的机会,类似于 Meltdown 攻击。

虽然 Meltdown 打破了用户空间到内核空间的保护,但 L1TF 允许攻击系统中的任何物理内存地址,并且该攻击在所有保护域中都有效。它允许攻击 SGX,并且由于推测绕过了扩展页表 (EPT) 保护机制,因此也可以从虚拟机内部进行攻击。

攻击场景

1. 恶意用户空间

操作系统在标记为不存在的 PTE 的地址位中存储任意信息。这允许恶意用户空间应用程序攻击这些 PTE 解析的物理内存。在某些情况下,用户空间可以恶意影响 PTE 地址位中编码的信息,从而使攻击更具确定性和实用性。

Linux 内核包含针对此攻击向量的缓解措施,即 PTE 反转,该措施永久启用,并且没有性能影响。内核确保未标记为存在的 PTE 的地址位永远不会指向可缓存的物理内存空间。

具有最新内核的系统可以防止来自恶意用户空间应用程序的攻击。

2. 虚拟机中的恶意来宾

L1TF 打破所有域保护的事实允许可以直接控制 PTE 的恶意来宾操作系统,以及在缺乏针对 L1TF 的 PTE 反转缓解措施的未受保护的来宾内核上运行的恶意来宾用户空间应用程序,来攻击物理主机内存。

L1TF 在虚拟化环境中的一个特殊方面是对称多线程 (SMT)。Intel 的 SMT 实现称为超线程。受影响的处理器上的超线程共享 L1 数据缓存 (L1D) 的事实对于这一点很重要。由于该缺陷只允许攻击存在于 L1D 中的数据,因此在一个超线程上运行的恶意来宾可以攻击由在同一物理内核的同级超线程上运行的上下文带入 L1D 的数据。此上下文可以是主机操作系统、主机用户空间或其他来宾。

如果处理器不支持扩展页表,则只有当虚拟机监控程序未清理有效(阴影)页表的内容时,才有可能进行攻击。

虽然存在完全缓解这些攻击向量的解决方案,但这些缓解措施默认情况下未在 Linux 内核中启用,因为它们会严重影响性能。内核提供了几种机制,可用于根据部署场景解决问题。以下部分介绍了缓解措施、它们的保护范围和影响。

本文档末尾解释了默认缓解措施以及选择它们的理由。请参阅 默认缓解措施

L1TF 系统信息

Linux 内核提供了一个 sysfs 接口来枚举系统的当前 L1TF 状态:系统是否容易受到攻击,以及哪些缓解措施处于活动状态。相关的 sysfs 文件是

/sys/devices/system/cpu/vulnerabilities/l1tf

此文件中的可能值是

“不受影响”

处理器不易受攻击

“缓解措施:PTE 反转”

主机保护处于活动状态

如果启用 KVM/VMX 并且处理器容易受到攻击,则以下信息将附加到“缓解措施:PTE 反转”部分

  • SMT 状态

    “VMX:SMT 易受攻击”

    已启用 SMT

    “VMX:SMT 已禁用”

    已禁用 SMT

  • L1D 刷新模式

    “L1D 易受攻击”

    L1D 刷新已禁用

    “L1D 条件缓存刷新”

    有条件地启用 L1D 刷新

    “L1D 缓存刷新”

    无条件启用 L1D 刷新

以下部分讨论了产生的保护等级。

主机缓解机制

内核无条件地防止来自主机上运行的恶意用户空间的 L1TF 攻击。

来宾缓解机制

1. VMENTER 上的 L1D 刷新

为了确保来宾无法攻击 L1D 中存在的数据,虚拟机监控程序会在进入来宾之前刷新 L1D。

刷新 L1D 不仅会逐出不应由潜在的恶意来宾访问的数据,还会刷新来宾数据。刷新 L1D 会对性能产生影响,因为处理器必须将刷新的来宾数据带回到 L1D 中。根据 VMEXIT/VMENTER 的频率以及来宾中的计算类型,已观察到 1% 到 50% 的性能下降。对于来宾 VMEXIT/VMENTER 很少的情况,性能影响是最小的。Virtio 和诸如发布中断之类的机制旨在将 VMEXIT 限制在最低限度,但特定配置和应用程序场景可能仍然会遭受较高的 VMEXIT 速率。

内核提供两种 L1D 刷新模式
  • 条件 (“cond”)

  • 无条件 (“always”)

条件模式避免了在执行相应的 VMENTER 之前仅执行经过审计的代码路径的 VMEXIT 之后刷新 L1D。这些代码路径已验证,它们不会向攻击者暴露秘密或其他敏感数据,但它们可能会泄露有关 hypervisor 地址空间布局的信息。

无条件模式在所有 VMENTER 调用时刷新 L1D,并提供最大程度的保护。它比条件模式具有更高的开销。由于它取决于工作负载场景和产生的 VMEXIT 数量,因此无法正确量化开销。

一般建议是在 VMENTER 上启用 L1D 刷新。内核在受影响的处理器上默认为条件模式。

请注意,L1D 刷新并不能防止 SMT 问题,因为同级线程也会将其数据带回 L1D,使其再次受到攻击。

管理员可以通过内核命令行和 sysfs 控制文件来控制 L1D 刷新。请参阅内核命令行上的缓解控制KVM 的缓解控制 - 模块参数

2. 将 Guest VCPU 限制到专用物理内核

为了解决 SMT 问题,可以将一个或一组 guest 关联到一个或多个物理内核。适当的机制是利用独占 cpusets 来确保没有其他 guest 或主机任务可以在这些内核上运行。

如果只有一个 guest 或相关的 guest 在同一物理内核上的同级 SMT 线程上运行,那么它们只能攻击自己的内存和主机内存的受限部分。

当一个同级 SMT 线程在主机操作系统(hypervisor)上下文中运行,而另一个在 guest 上下文中运行时,主机内存是可攻击的。主机操作系统上下文中提供的有价值信息量取决于主机操作系统执行的上下文,即中断、软中断和内核线程。在未对代码进行深入检查的情况下,不能将这些上下文中的有价值数据声明为对攻击者不感兴趣。

请注意,将 guest 分配到固定的物理内核集会影响调度程序进行负载平衡的能力,并且可能会对 CPU 利用率产生负面影响,具体取决于托管场景。禁用 SMT 可能是特定场景的可行替代方案。

有关将 guest 限制为单个或一组内核的更多信息,请查阅 cpusets 文档

https://linuxkernel.org.cn/doc/Documentation/admin-guide/cgroup-v1/cpusets.rst

3. 中断关联性

中断可以关联到逻辑 CPU。这并非普遍适用,因为存在一些真正属于每个 CPU 的中断类型,例如本地定时器中断。除此之外,多队列设备将其中断关联到单个 CPU 或每个队列的 CPU 组,而不允许管理员控制关联性。

将可以控制关联性的中断从运行不受信任 guest 的 CPU 中移开,可以减少攻击向量空间。

与运行不受信任 guest 的 CPU 关联的中断是否为攻击者提供感兴趣的数据取决于系统配置和系统上运行的场景。虽然对于某些中断,可以假设它们不会暴露除暴露有关主机操作系统内存布局的提示之外的任何有趣信息,但没有办法做出一般性假设。

管理员可以通过 /proc/irq/$NR/smp_affinity[_list] 文件来控制中断关联性。有限的文档可在以下位置获得

https://linuxkernel.org.cn/doc/Documentation/core-api/irq/irq-affinity.rst

4. SMT 控制

为了防止 L1TF 的 SMT 问题,可能需要完全禁用 SMT。禁用 SMT 可能会对性能产生重大影响,但影响取决于托管场景和工作负载的类型。还需要权衡禁用 SMT 的影响与其他缓解解决方案(如将 guest 限制到专用内核)的影响。

内核提供了一个 sysfs 接口来检索 SMT 的状态并控制它。它还提供了一个内核命令行接口来控制 SMT。

内核命令行接口包含以下选项

nosmt

影响启动期间辅助 CPU 的启动。内核尝试在启动过程中将所有存在的 CPU 联机。“nosmt”确保每个物理内核只有一个 - 所谓的 primary(超)线程被激活。由于 Intel 处理器与机器检查异常相关的设计缺陷,非 primary 的同级线程必须至少部分启动,然后再次关闭。“nosmt”可以通过 sysfs 接口撤消。

nosmt=force

具有与“nosmt”相同的效果,但不允许通过 sysfs 接口撤消 SMT 禁用。

sysfs 接口提供两个文件

  • /sys/devices/system/cpu/smt/control

  • /sys/devices/system/cpu/smt/active

/sys/devices/system/cpu/smt/control

此文件允许读取 SMT 控制状态,并提供禁用或(重新)启用 SMT 的能力。可能的状态是

on

CPU 支持并启用了 SMT。所有逻辑 CPU 都可以不受限制地上线和离线。

off

CPU 支持并禁用了 SMT。只有所谓的 primary SMT 线程可以不受限制地上线和离线。尝试上线非 primary 的同级线程将被拒绝。

forceoff

与“off”相同,但状态无法控制。尝试写入控制文件将被拒绝。

notsupported

处理器不支持 SMT。因此它不受 L1TF 的 SMT 影响。尝试写入控制文件将被拒绝。

可以写入此文件以控制 SMT 状态的可能状态是

  • on

  • off

  • forceoff

/sys/devices/system/cpu/smt/active

此文件报告是否启用并激活了 SMT,即是否在任何物理内核上两个或多个同级线程在线。

也可以在启动时通过 l1tf 内核命令行参数与 L1D 刷新控制相结合来控制 SMT。请参阅内核命令行上的缓解控制

5. 禁用 EPT

禁用虚拟机的 EPT 可以为 L1TF 提供全面的缓解,即使启用了 SMT,因为 guest 的有效页表是由 hypervisor 管理和清理的。尽管禁用 EPT 会对性能产生重大影响,尤其是在启用 Meltdown 缓解 KPTI 时。

可以通过 “kvm-intel.ept” 参数在 hypervisor 中禁用 EPT。

正在进行针对新的缓解机制的研究和开发,以解决禁用 SMT 或 EPT 的性能影响。

内核命令行上的缓解控制

内核命令行允许在启动时使用选项 “l1tf=” 来控制 L1TF 缓解。此选项的有效参数为

full

为 L1TF 漏洞提供所有可用的缓解措施。禁用 SMT 并启用 hypervisor 中的所有缓解措施,即无条件 L1D 刷新

启动后仍然可以通过 sysfs 接口控制 SMT 和 L1D 刷新。当在潜在不安全的配置(即启用 SMT 或禁用 L1D 刷新)中启动第一个 VM 时,Hypervisor 将发出警告。

full,force

与 ‘full’ 相同,但禁用 SMT 和 L1D 刷新运行时控制。意味着 ‘nosmt=force’ 命令行选项。(即禁用 SMT 的 sysfs 控制。)

flush

保持 SMT 启用并启用默认 hypervisor 缓解,即有条件 L1D 刷新

启动后仍然可以通过 sysfs 接口控制 SMT 和 L1D 刷新。当在潜在不安全的配置(即启用 SMT 或禁用 L1D 刷新)中启动第一个 VM 时,Hypervisor 将发出警告。

flush,nosmt

禁用 SMT 并启用默认 hypervisor 缓解,即有条件 L1D 刷新。

启动后仍然可以通过 sysfs 接口控制 SMT 和 L1D 刷新。当在潜在不安全的配置(即启用 SMT 或禁用 L1D 刷新)中启动第一个 VM 时,Hypervisor 将发出警告。

flush,nowarn

与 ‘flush’ 相同,但是当在潜在不安全的配置中启动 VM 时,hypervisor 不会发出警告。

off

禁用 hypervisor 缓解措施,并且不发出任何警告。它还会降低 hypervisor 和裸机上的交换空间和可用 RAM 限制。

默认值为 ‘flush’。有关 L1D 刷新的详细信息,请参阅1. VMENTER 上的 L1D 刷新

KVM 的缓解控制 - 模块参数

KVM hypervisor 缓解机制,即在进入 guest 时刷新 L1D 缓存,可以使用模块参数进行控制。

选项/参数为 “kvm-intel.vmentry_l1d_flush=”。它采用以下参数

always

在每次 VMENTER 时刷新 L1D 缓存。

cond

仅当 VMEXIT 和 VMENTER 之间的代码可能泄漏攻击者认为感兴趣的主机内存时,才在 VMENTER 上刷新 L1D。这仍然会泄漏主机内存,例如,允许确定主机地址空间布局。

never

禁用缓解措施

该参数可以在内核命令行上提供,作为加载模块时的模块参数,并且可以在运行时通过 sysfs 文件进行修改

/sys/module/kvm_intel/parameters/vmentry_l1d_flush

默认值为 ‘cond’。如果在内核命令行上给出了 ‘l1tf=full,force’,则强制执行 ‘always’,并且将忽略 kvm-intel.vmentry_l1d_flush 模块参数,并且对 sysfs 文件的写入将被拒绝。

缓解措施选择指南

1. 未使用虚拟化

系统受到内核的无条件保护,无需进一步操作。

2. 使用受信任 guest 的虚拟化

如果 guest 来自受信任的来源,并且保证 guest 操作系统内核已实施 L1TF 缓解措施,则系统可以完全防止 L1TF 攻击,无需进一步操作。

为了避免在 VMENTER 上默认 L1D 刷新的开销,管理员可以通过内核命令行和 sysfs 控制文件禁用刷新。请参阅内核命令行上的缓解控制KVM 的缓解控制 - 模块参数

3. 使用不受信任 guest 的虚拟化

3.1. 不支持或禁用 SMT

如果处理器不支持 SMT,或者在 BIOS 或内核中禁用 SMT,则只需要在 VMENTER 上强制执行 L1D 刷新。

条件 L1D 刷新是默认行为,可以进行调整。请参阅内核命令行上的缓解控制KVM 的缓解控制 - 模块参数

3.2. 不支持或禁用 EPT

如果处理器不支持 EPT 或在虚拟机管理程序中禁用 EPT,则系统将受到完全保护。 SMT 可以保持启用状态,并且不需要在 VMENTER 上进行 L1D 刷新。

可以通过 “kvm-intel.ept” 参数在 hypervisor 中禁用 EPT。

3.3. 支持并启用 SMT 和 EPT

如果支持并启用 SMT 和 EPT,则可以采用各种程度的缓解措施。

  • 在 VMENTER 上进行 L1D 刷新

    在 VMENTER 上进行 L1D 刷新是最低限度的保护要求,但它只有与其他缓解方法结合使用时才有效。

    条件 L1D 刷新是默认行为,可以进行调整。请参阅内核命令行上的缓解控制KVM 的缓解控制 - 模块参数

  • 客户机限制

    将客户机限制在单个或一组未运行任何其他进程的物理内核上,可以显著减少攻击面,但中断、软中断和内核线程仍然可能向潜在攻击者暴露有价值的数据。请参阅2. 将客户机 VCPU 限制到专用的物理内核

  • 中断隔离

    将客户机 CPU 与中断隔离可以进一步减少攻击面,但仍然允许恶意客户机探索有限数量的主机物理内存。这至少可以用来获取有关主机地址空间布局的知识。根据具体情况,固定绑定到运行不受信任客户机的 CPU 的中断仍然可以触发软中断并调度可能暴露有价值信息的内核线程。请参阅3. 中断亲和性

以上三种缓解方法结合使用可以提供一定程度的保护,但必须仔细分析剩余攻击面的风险。为了获得全面保护,可以使用以下方法。

  • 禁用 SMT

    禁用 SMT 并强制执行 L1D 刷新可提供最大程度的保护。这种缓解措施不依赖于上述任何缓解方法。

    SMT 控制和 L1D 刷新可以通过命令行参数 ‘nosmt’、‘l1tf’、‘kvm-intel.vmentry_l1d_flush’ 以及运行时使用匹配的 sysfs 控制文件进行调整。请参阅4. SMT 控制内核命令行上的缓解控制KVM 的缓解控制 - 模块参数

  • 禁用 EPT

    禁用 EPT 也可提供最大程度的保护。它不依赖于上述任何缓解方法。SMT 可以保持启用状态,并且不需要 L1D 刷新,但性能影响很大。

    可以通过 “kvm-intel.ept” 参数在 hypervisor 中禁用 EPT。

3.4. 嵌套虚拟机

当使用嵌套虚拟化时,涉及三个操作系统:裸机虚拟机管理程序、嵌套虚拟机管理程序和嵌套虚拟机。从嵌套虚拟机管理程序到嵌套客户机的 VMENTER 操作将始终由裸机虚拟机管理程序处理。如果 KVM 是裸机虚拟机管理程序,它将

  • 在每次从嵌套虚拟机管理程序切换到嵌套虚拟机时刷新 L1D 缓存,以便嵌套虚拟机管理程序的机密不会暴露给嵌套虚拟机;

  • 在每次从嵌套虚拟机切换到嵌套虚拟机管理程序时刷新 L1D 缓存;这是一个复杂的操作,刷新 L1D 缓存可以避免裸机虚拟机管理程序的机密暴露给嵌套虚拟机;

  • 指示嵌套虚拟机管理程序不要执行任何 L1D 缓存刷新。这是一种避免双重 L1D 刷新的优化。

默认缓解措施

内核针对易受攻击的处理器的默认缓解措施是

  • PTE 反转以防止恶意用户空间。这是无条件完成的,无法控制。交换存储限制为约 16TB。

  • 当为客户机启用 EPT 时,在 VMENTER 上进行 L1D 条件刷新。

默认情况下,内核不会强制禁用 SMT,这使得在启用 EPT 的情况下运行不受信任的客户机时,SMT 系统容易受到攻击。

此选择的理由是

  • 强制禁用 SMT 可能会破坏现有设置,尤其是在无人值守更新的情况下。

  • 如果普通用户在其机器上运行不受信任的客户机,那么 L1TF 只是对可能嵌入在不受信任的客户机中的其他恶意软件(例如,垃圾邮件机器人或对本地网络的攻击)的附加项。

    没有技术方法可以阻止用户在其机器上盲目运行不受信任的代码。

  • 从技术上讲,L1TF 通过最流行的攻击机制(如 JavaScript)被利用的可能性极低,甚至根据目前的知识是不可能的,因为这些机制无法控制 PTE。如果这是可能且无法采取其他缓解措施,那么默认值可能会有所不同。

  • 云和托管设置的管理员必须仔细分析其场景的风险,并做出适当的缓解选择,这些选择甚至可能因其部署的机器而异,并导致其整体设置的其他更改。内核无法为此类场景提供合理的默认值。