23. 微架構資料取樣 (MDS) 緩解

23.1. 概述

微架構資料取樣 (MDS) 是 Intel CPU 中內部緩衝區的一系列側通道攻擊。 變種包括:

  • 微架構儲存緩衝區資料取樣 (MSBDS) (CVE-2018-12126)

  • 微架構填充緩衝區資料取樣 (MFBDS) (CVE-2018-12130)

  • 微架構載入埠資料取樣 (MLPDS) (CVE-2018-12127)

  • 微架構資料取樣不可快取記憶體 (MDSUM) (CVE-2019-11091)

MSBDS 洩漏儲存緩衝區條目,這些條目可以推測性地轉發到依賴載入(store-to-load forwarding)作為一種最佳化。 轉發也可能發生在不同記憶體地址的故障或輔助載入操作中,這在某些條件下可以被利用。 儲存緩衝區在超執行緒之間進行分割槽,因此不可能進行跨執行緒轉發。 但是,如果一個執行緒進入或退出睡眠狀態,儲存緩衝區會被重新分割槽,這可能會將一個執行緒的資料暴露給另一個執行緒。

MFBDS 洩漏填充緩衝區條目。 填充緩衝區在內部用於管理 L1 未命中情況,並儲存響應記憶體或 I/O 操作而返回或傳送的資料。 填充緩衝區可以將資料轉發到載入操作,也可以將資料寫入快取。 當填充緩衝區被釋放時,它可以保留先前操作的陳舊資料,然後這些資料可以轉發到故障或輔助載入操作,這在某些條件下可以被利用。 填充緩衝區在超執行緒之間共享,因此可能發生跨執行緒洩漏。

MLPDS 洩漏載入埠資料。 載入埠用於執行來自記憶體或 I/O 的載入操作。 然後,接收到的資料被轉發到暫存器檔案或後續操作。 在某些實現中,載入埠可能包含來自先前操作的陳舊資料,這些資料可以在某些條件下轉發到故障或輔助載入,這又可以最終被利用。 載入埠在超執行緒之間共享,因此可能發生跨執行緒洩漏。

MDSUM 是 MSBDS、MFBDS 和 MLPDS 的一個特例。 來自記憶體的不可快取載入,如果發生故障或輔助,可能會在微架構結構中留下資料,這些資料稍後可以使用 MSBDS、MFBDS 或 MLPDS 使用的相同方法進行觀察。

23.2. 暴露假設

假設攻擊程式碼駐留在使用者空間或 guest 中,但有一個例外。 此假設背後的理由是,利用 MDS 所需的程式碼結構需要:

  • 控制載入以觸發故障或輔助

  • 擁有一個披露小工具,透過側通道暴露推測性訪問的資料以供使用。

  • 控制披露小工具暴露資料的指標

不能 100% 排除核心中存在這種結構的可能性,但涉及的複雜性使其極不可能。

有一個例外,即不受信任的 BPF。 不受信任的 BPF 的功能有限,但需要徹底調查它是否可以用於建立這種結構。

23.3. 緩解策略

所有變種至少在單 CPU 執行緒情況下(關閉 SMT)具有相同的緩解策略:強制 CPU 清除受影響的緩衝區。

這是透過結合微碼更新使用原本未使用且已過時的 VERW 指令來實現的。 執行 VERW 指令時,微碼會清除受影響的 CPU 緩衝區。

對於虛擬化,有兩種方法可以實現 CPU 緩衝區清除。 可以使用修改後的 VERW 指令,也可以透過 L1D Flush 命令。 後者在啟用 L1TF 緩解時發出,因此可以避免額外的 VERW。 如果 CPU 不受 L1TF 影響,則需要發出 VERW。

如果在沒有微碼更新的 CPU 上執行帶有提供的段選擇器引數的 VERW 指令,除了浪費少量 CPU 週期之外,不會產生任何副作用。

這不能防止跨超執行緒攻擊,除了 MSBDS 僅在其中一個超執行緒進入 C 狀態時才可跨超執行緒利用。

核心提供了一個函式來呼叫緩衝區清除

mds_clear_cpu_buffers()

此外,宏 CLEAR_CPU_BUFFERS 可用於 exit-to-user 路徑中的 ASM 末尾。 除了 CFLAGS.ZF 之外,此宏不會破壞任何暫存器。

緩解措施在核心/使用者空間、虛擬機器管理程式/guest 和 C 狀態(空閒)轉換時呼叫。

作為解決虛擬化場景的特殊怪癖,如果主機更新了微碼,但虛擬機器管理程式(尚未)向 guest 公開 MD_CLEAR CPUID 位,則核心會發出 VERW 指令,希望它可以實際清除緩衝區。 狀態會相應地反映出來。

根據目前的瞭解,核心本身不需要額外的緩解措施,因為暴露洩漏資料的必要小工具無法以允許從惡意使用者空間或 VM guest 進行利用的方式進行控制。

23.4. 核心內部緩解模式

off

緩解已停用。 CPU 不受影響,或者在核心命令列上提供了 mds=off

full

緩解已啟用。 CPU 受影響,並且在 CPUID 中聲明瞭 MD_CLEAR。

vmwerv

緩解已啟用。 CPU 受影響,並且未在 CPUID 中宣告 MD_CLEAR。 這主要用於虛擬化場景,其中主機更新了微碼,但虛擬機器管理程式未在 CPUID 中暴露 MD_CLEAR。 這是一種盡力而為的方法,沒有保證。

如果 CPU 受影響,並且未在核心命令列上提供 mds=off,則核心會根據 MD_CLEAR CPUID 位的可用性選擇適當的緩解模式。

23.5. 緩解點

23.5.1. 1. 返回使用者空間

當從核心轉換到使用者空間時,如果未在核心命令列上停用緩解,則會在受影響的 CPU 上重新整理 CPU 緩衝區。 透過特性標誌 X86_FEATURE_CLEAR_CPU_BUF 啟用緩解。

在使用者暫存器恢復後,緩解措施會在轉換到使用者空間之前呼叫。 這樣做是為了最小化在 VERW 之後可以訪問核心資料的視窗,例如透過 VERW 後的 NMI。

未處理的極端情況 返回核心的中斷不會清除 CPU 緩衝區,因為 exit-to-user 路徑無論如何都會這樣做。 但是,可能會出現這樣一種情況:在 exit-to-user 路徑清除緩衝區後,在核心中生成了 NMI。 這種情況未得到處理,返回核心的 NMI 不會清除 CPU 緩衝區,因為

  1. 在 VERW 之後但在返回使用者空間之前獲得 NMI 的情況很少見。

  2. 對於非特權使用者,沒有已知的方法可以使 NMI 不那麼罕見或針對它。

  3. 需要大量這些精確計時的 NMI 才能發起實際攻擊。 據推測沒有足夠的頻寬。

  4. 所討論的 NMI 發生在 VERW 之後,即當用戶狀態恢復並且大多數有趣的資料已經被清除時。 剩下的只是 NMI 觸控的資料,這些資料可能有用也可能沒有用。

23.5.2. 2. C 狀態轉換

當 CPU 進入空閒狀態並進入 C 狀態時,當 SMT 處於活動狀態時,需要在受影響的 CPU 上清除 CPU 緩衝區。 這解決了其中一個超執行緒進入 C 狀態時儲存緩衝區的重新分割槽問題。

當 SMT 不活動時,即 CPU 不支援 SMT 或所有兄弟執行緒都處於離線狀態時,不需要清除 CPU 緩衝區。

空閒清除在僅受 MSBDS 影響而不受任何其他 MDS 變種影響的 CPU 上啟用。 其他 MDS 變種無法防止跨超執行緒攻擊,因為填充緩衝區和載入埠是共享的。 因此,在受其他變種影響的 CPU 上,空閒清除將是一種表面文章,因此不會啟用。

呼叫由靜態鍵 mds_idle_clear 控制,該靜態鍵根據所選的緩解模式和系統的 SMT 狀態進行切換。

僅在進入 C 狀態之前呼叫緩衝區清除,以防止來自空閒 CPU 的陳舊資料在儲存緩衝區重新分割槽後溢位到超執行緒兄弟執行緒,並且所有條目都可供非空閒兄弟執行緒使用。

當從空閒狀態退出時,儲存緩衝區會再次分割槽,因此每個兄弟執行緒都有一半可用。 然後,從空閒狀態返回的 CPU 可能會推測性地暴露給兄弟執行緒的內容。 緩衝區會在退出到使用者空間或 VMENTER 時重新整理,因此使用者空間或 guest 中的惡意程式碼無法推測性地訪問它們。

緩解措施已連線到所有變體的 halt()/mwait(),但不包括傳統的 ACPI IO 埠機制,因為 ACPI 空閒驅動程式已在 2010 年左右被 intel_idle 驅動程式取代,並且在所有受影響的 CPU 上都首選 intel_idle 驅動程式,預計這些 CPU 將在微碼中獲得 MD_CLEAR 功能。 除此之外,IO 埠機制是一個傳統介面,僅用於較舊的系統,這些系統要麼不受影響,要麼不再接收微碼更新。