推測性返回棧溢位(SRSO)¶
這是針對 AMD 處理器上發現的推測性返回棧溢位(SRSO)漏洞的一種緩解措施。該機制是眾所周知的場景:毒化 CPU 功能單元——在本例中是分支目標緩衝區(BTB)和返回地址預測器(RAP)——然後誘騙特權提升域(核心)洩露敏感資料。
AMD CPU 使用返回地址預測器(又稱返回地址棧/返回棧緩衝區)預測 RET 指令。在某些情況下,一個非架構性 CALL 指令(即,一個被預測為 CALL 但實際不是 CALL 的指令)可以在 RAP 中建立一個條目,該條目可能被用來預測後續 RET 指令的目標。
導致這種情況的具體情況因微架構而異,但令人擔憂的是,攻擊者可以錯誤地訓練 CPU BTB,使其在核心空間中預測非架構性 CALL 指令,並利用這一點來控制後續核心 RET 的推測目標,從而可能透過推測性旁道導致資訊洩露。
此問題在 CVE-2023-20569 中進行跟蹤。
受影響的處理器¶
AMD Zen,第 1-4 代。即所有 0x17 和 0x19 系列。未對舊處理器進行調查。
系統資訊和選項¶
首先,需要載入最新的微碼以使緩解措施生效。
顯示 SRSO 緩解狀態的 sysfs 檔案是
/sys/devices/system/cpu/vulnerabilities/spec_rstack_overflow
此檔案中可能的值為
“不受影響”
處理器不受漏洞影響
“易受攻擊”
處理器易受攻擊,且未應用任何緩解措施。
“易受攻擊:無微碼”
處理器易受攻擊,未應用擴充套件 IBPB 功能以解決此漏洞的微碼。
“易受攻擊:安全 RET,無微碼”
“安全 RET”緩解措施(見下文)已應用於保護核心,但未應用擴充套件 IBPB 的微碼。使用者空間任務仍可能易受攻擊。
“易受攻擊:微碼,無安全 RET”
已應用擴充套件 IBPB 功能的微碼補丁。它不解決使用者->核心和訪客->主機轉換保護問題,但解決了使用者->使用者和虛擬機器->虛擬機器攻擊向量問題。
請注意,使用者->使用者緩解受 Spectre v2 緩解中 IBPB 方面如何選擇的控制
條件 IBPB
每個程序可以選擇是否需要圍繞其發出 IBPB(PR_SPEC_DISABLE/_ENABLE 等),詳見Spectre 旁道
嚴格
即,始終開啟——透過在核心命令列中提供 spectre_v2_user=on
(spec_rstack_overflow=microcode)
“緩解:安全 RET”
微碼/軟體組合緩解。它透過解決使用者->核心和訪客->主機轉換保護來補充擴充套件 IBPB 微碼補丁的功能。
預設選擇或透過 spec_rstack_overflow=safe-ret 選擇
“緩解:IBPB”
與上述“安全 RET”類似的保護,但在特權域交叉(使用者->核心,訪客->主機)時採用 IBPB 屏障。
(spec_rstack_overflow=ibpb)
“緩解:VMEXIT 時的 IBPB”
緩解針對雲提供商場景——僅訪客->主機轉換。
(spec_rstack_overflow=ibpb-vmexit)
“緩解:推測減少”
當選擇了上述“VMEXIT 時的 IBPB”且 CPU 支援 BpSpecReduce 位時,此緩解措施會自動啟用。
在具有 SRSO_USER_KERNEL_NO=1 CPUID 位的機器上,它會自動啟用。在這種情況下,程式碼邏輯是切換到上述 =ibpb-vmexit 緩解,因為使用者/核心邊界不再受影響,因此不需要“安全 RET”。
啟用 VMEXIT 時的 IBPB 緩解選項後,會檢測到 BpSpecReduce 位(所有此類機器都具有此功能),這實際上會覆蓋 VMEXIT 時的 IBPB,因為它對效能影響小得多,並且也能處理訪客->主機攻擊向量。
為了利用此漏洞,攻擊者需要
在機器上獲得本地訪問許可權
打破 kASLR
在執行中的核心中找到小工具以用於利用
可能在同級執行緒上建立並固定額外的工作負載,具體取決於微架構(在 0x19 家族上不必要)
執行漏洞利用
考慮到每種緩解型別的效能影響,預設的是“緩解:安全 RET”,它應該能處理大多數攻擊向量,包括本地使用者->核心攻擊。
與往常一樣,建議使用者透過定期應用軟體更新來保持其系統最新。
預設設定將根據需要重新評估,尤其是在出現新的攻擊向量時。
正如人們可以推測的那樣,“緩解:安全 RET”會以犧牲一些效能為代價,具體取決於工作負載。如果使用者信任其使用者空間並且不想承受效能影響,則始終可以使用 spec_rstack_overflow=off 停用緩解措施。
類似地,“緩解:IBPB”是另一種完整的緩解型別,它在為系統應用所需的微碼補丁後,採用間接分支預測屏障。這種緩解措施也會帶來效能成本。
緩解:安全 RET¶
該緩解措施透過確保所有 RET 指令推測到受控位置來工作,類似於在 retpoline 序列中控制推測的方式。為了實現這一點,__x86_return_thunk 強制 CPU 使用“安全返回”序列錯誤預測每次函式返回。
為確保此緩解措施的安全性,核心必須確保安全返回序列本身不受攻擊者干擾。在 Zen3 和 Zen4 中,這是透過在未訓練函式 srso_alias_untrain_ret() 和安全返回函式 srso_alias_safe_ret() 之間建立 BTB 別名來實現的,這會驅逐潛在的被毒化 BTB 條目,並使用該安全條目進行所有函式返回。
在較舊的 Zen1 和 Zen2 中,這是透過類似於 Retbleed 的重新解釋技術實現的:srso_untrain_ret() 和 srso_safe_ret()。
檢查安全 RET 緩解措施是否實際有效¶
如果想驗證 SRSO 安全 RET 緩解措施是否在核心上有效,可以使用兩個效能計數器
PMC_0xc8 - 已退休的 RET/RET lw 計數
PMC_0xc9 - 已退休且錯誤預測的 RET/RET lw 計數
並比較核心模式下正確退休的 RET 數量與錯誤預測退休的 RET 數量。另一種指定這些事件的方法是
# perf list ex_ret_near_ret
List of pre-defined events (to be used in -e or -M):
core:
ex_ret_near_ret
[Retired Near Returns]
ex_ret_near_ret_mispred
[Retired Near Returns Mispredicted]
使用事件助記符的命令
# perf stat -e ex_ret_near_ret:k -e ex_ret_near_ret_mispred:k sleep 10s
或使用原始 PMC 編號
# perf stat -e cpu/event=0xc8,umask=0/k -e cpu/event=0xc9,umask=0/k sleep 10s
應該給出相同的數量。即,每個退休的 RET 都應該被錯誤預測
[root@brent: ~/kernel/linux/tools/perf> ./perf stat -e cpu/event=0xc8,umask=0/k -e cpu/event=0xc9,umask=0/k sleep 10s
Performance counter stats for 'sleep 10s':
137,167 cpu/event=0xc8,umask=0/k
137,173 cpu/event=0xc9,umask=0/k
10.004110303 seconds time elapsed
0.000000000 seconds user
0.004462000 seconds sys
與緩解措施被停用(spec_rstack_overflow=off)或未能正常工作的情況相比,後者通常顯示在工作負載期間錯誤預測退休的 RET 數量遠小於退休的 RET 總數
[root@brent: ~/kernel/linux/tools/perf> ./perf stat -e cpu/event=0xc8,umask=0/k -e cpu/event=0xc9,umask=0/k sleep 10s
Performance counter stats for 'sleep 10s':
201,627 cpu/event=0xc8,umask=0/k
4,074 cpu/event=0xc9,umask=0/k
10.003267252 seconds time elapsed
0.002729000 seconds user
0.000000000 seconds sys
此外,有一個自測試會執行上述操作,請前往 tools/testing/selftests/x86/ 並執行
make srso
./srso