本文將介紹近年興起的機密虛擬機(Confidential Virtual Machine)技術所旨在抵御的威脅模型,主要關注內存機密性(confidentiality)和內存完整性(integrity)兩個方面。在解釋該威脅可能造成的問題的同時,還將同時介紹現在最主流的機密虛擬機解決方案之一的 AMD SEV-SNP 如何如何應對該威脅。
在正式介紹之前,有必要先明確這樣一個概念,在機密虛擬機的威脅模型中,Hypervisor 被認為是不可信的。惡意的 Hypervisor 可能讀取虛擬機的內存數據,導致虛擬機用戶隱私泄露;或是直接寫入虛擬機內存,導致虛擬機運行產生預期之外的結果。
機密性
虛擬機內存
由于虛擬機的內存是通過第二階段頁表映射(GPA -> HPA)到宿主機內存中,且該頁表由 Hypervisor 進行維護。因此在未引入機密虛擬機技術時,Hypervisor 能夠直接借助該頁表映射,手動進行地址轉換并讀取虛擬機內存數據。
對于虛擬機內存的機密性,AMD 在最早的 SEV 技術(2016 年)中已經解決。解決方法是為每個虛擬機引入一個 AES 加密密鑰,虛擬機指定為私有的頁面在被讀寫時將會自動地進行加解密,這一過程對于虛擬機而言完全無感。當 Hypervisor 嘗試讀取虛擬機的私有內存數據時,只會讀取到被加密過的密文數據,保障了數據的機密性。
虛擬機寄存器狀態
虛擬機在 VM Exit 到 Hypervisor 時,需要將此時的 CPU 狀態,即寄存器狀態進行保存(通常保存在一個數據結構中,AMD-V 虛擬機為 VMCB)。而 Hypervisor 就能在重新 VM Entry 到虛擬機前,很輕松地讀取其中的內容。
AMD 在 2017 年引入了 SEV-ES(Encrypted State)特性,在發生 VM Exit 時,虛擬機寄存器內容會被自動加密,并存入加密的 VMSA(Virtual Machine Save Area)中,原有的 VMCB 中的被加密字段存儲著指向被加密數據區域的指針 VMSA_POINTER
,Hypervisor 無法讀取到具體內容。
完整性
內存加密只解決了 Hypervisor 惡意讀取虛擬機數據的問題,Hypervisor 仍然可以在不知道數據具體內容的情況下,惡意地對虛擬機內存進行寫入,從而破壞虛擬機內存數據,造成預料之外的結果。
AMD 在 2020 年引入了 SEV-SNP 擴展,引入了對虛擬機完整性保護的支持。核心機制是 只有內存頁面的擁有者才能夠寫入該頁面 。具體實現方式是引入了新的數據結構 RMP(Reverse Map Table),RMP 是一個在整個系統中共享的單一數據結構,它包含了每個虛擬機可能使用的 HPA 頁面的條目。RMP 的作用是為了跟蹤每個內存頁面的擁有者。
RMP 表不能直接被寫入,需要通過 SEV-SNP 引入的新的 CPU 指令來操作。
RMP 檢查在虛擬地址通過 Page Walk 得到 HPA 后進行,無論是 Hypervisor 還是虛擬機都需要進行。對于 Hypervisor 而言,它無需進行兩階段地址翻譯,因此在完成 VA -> PA
后,查看 PA 對應的 RMP 條目,驗證本頁面是否屬于 Hypervisor;對于虛擬機而言,它在完成 GVA -> GPA -> HPA
后, 查看 HPA 對應的 RMP 條目,檢查本次訪存是否合法(具體檢查內容下文詳細討論)。
數據重放(Data Replay)
攻擊方式
在引入虛擬機內存加密的情況下,雖然無法直接得知從虛擬機中讀取到的內存數據的內容,但由于寫入操作不受限制,因此惡意的 Hypervisor 可以將從某個內存頁處讀取到的舊數據保存起來,在未來的某個時刻將這些舊數據進行重放。
注意,Hypervisor 由于沒有被分配 AES 密鑰,因此讀取到的數據為密文。此時 Hypervisor 不必知道這段密文內容是什么,只需要知道它可能代表了虛擬機某一時刻的狀態,Hypervisor 可以在未來的某個時刻將這段密文數據覆寫到原來的內存位置,即將虛擬機的某段內存狀態進行回退,從而實施可能的攻擊。
由于 AES 加密為對稱式加密,因此寫入經同一個密鑰加密的密文數據效果就等同于直接寫入明文數據。
防御方式
目標: 只有內存頁面的擁有者才能寫入頁面。
在 RMP Check 時檢查 RMP 條目的 Assigned
, ASID
, Immutable
字段,驗證本次內存寫入者是否是頁面的擁有者。不同擁有者類型所對應的字段值如下表所示:
Owner | Assigned | ASID | Immutable |
---|---|---|---|
Hypervisor | 0 | 0 | - |
Guest | 1 | ASID of the guest | - |
AMD-SP | 1 | 0 | 1 |
數據污染(Data Corruption)
攻擊方式
惡意 Hypervisor 直接將垃圾數據寫入虛擬機的內存中,可能造成預期外的行為。
防御方式
目標: 同數據重放。
AMD SEV-SNP 實現方式:同數據重放。
內存混疊(Memory Aliasing)
攻擊方式
惡意 Hypervisor 通過直接寫入第二階段頁表,將多個 GPA 映射到同一個 HPA 上。這樣的“內存混疊”現象將很容易導致特定物理內存頁面的數據被污染,造成預期外的行為。
防御方式
目標: 每個 host 內存頁面在同一時間只能被一個 guest 內存頁面映射。
在 AMD SEV-SNP 中,RMP 條目引入了 Guest_Physical_Address
字段,保存了映射到本頁面的 GPA。在執行 RMP 檢查時,驗證發起本次訪存的 GPA 是否等于 Guest_Physical_Address
。
內存重映射(Memory Re-Mapping)
攻擊方式
惡意 Hypervisor 通過直接寫入第二階段頁表,將一個 GPA 映射到多個 HPA,或者更改它所映射的到的 HPA。這將導致虛擬機看到一個不連續的內存視圖(an inconsistent view of memory)。下面列舉一個可能的場景:
- Hypervisor 將虛擬地址
0x1000
映射到物理頁 P1; - 應用程序向
0x1000
寫入敏感數據。 - Hypervisor 修改頁表,將
0x1000
映射到物理頁 P2; - 應用程序再次讀取
0x1000
,發現數據不見了或變成了其他值; - 程序邏輯因此出錯,可能跳過安全檢查、泄露信息、甚至崩潰。
防御方式
目標: 每個 guest 內存頁面在同一時間只能映射一個 host 內存頁面。
AMD SEV-SNP 在 RMP 條目中引入 Validated
位,表示本頁面是否已經被驗證。每個頁面被創建時為未驗證狀態,必須要經過 PVALIDATE
指令驗證(驗證過程會檢測到是否存在一個 guest 頁面重復驗證的情況)后才能被寫入,頁面在被指令 RMPUPDATE
更新后又會變成未驗證狀態,此時需要重新驗證。