Linux 核心修復辦法:核心頁表隔離KPTl(kernel page table isolation)
-
每個程序一張頁表變成兩張:執行在核心態和執行在使用者態時分別使用各自分離的頁表
-
Kernel頁表包含了程序使用者空間地址的對映和Kernel使用的記憶體對映
-
使用者頁表僅僅包含了使用者空間的記憶體對映以及核心跳板的記憶體對映
-
當程序執行在使用者空間時,使用的是使用者頁表
-
當發生中斷或者是異常時,需要陷入到核心,進入核心空間後,有一小段核心跳板將頁表切換到核心頁表
-
KPTI最早是運用在x86上
-
KPTI補丁已經合併到Linux 4.15-rc4上
x86上的KPTI補丁主要工作:
- 核心頁表和使用者態頁表的分離和切換
- 程序切換的最佳化:
- 因為核心態的頁表包含了所有地址空間的頁表,所以可以安全的訪問到使用者態頁表
- 程序中使用者態到核心態之間的切換,需要切換CR3暫存器
- 採用per-cpu的PCID來最佳化
ARM上的KPTI
- ARM64 只有Cortex-A75中招Meltdown漏洞
ARM64上早已經採用了雙頁表的設計,但是。 - ARM64上KPTI 的最佳化:
- A75上雖然有兩個頁表暫存器,但是TLB上依然沒法做到完全隔離,使用者程序在meltdown情況下依然有可能訪問核心空間對映的TLB entry
- -個給當程序跑在核心態的使用,另外一個給程序跑在使用者態每個程序上的ASID設定兩份時使用。這樣原本核心空間屬於global TLB,就變成Process-Specific型別的TLB。
- ARM64上TLB示意圖
ASID的簡介
- 程序切換需要flush TLB,導致效能下降
- TLB最佳化:(ASID)Address Space ID
- Gobal型別的TLB:核心空間是所有程序共享的空間,因此這部分空間的虛擬地址到實體地址的翻譯是不會變化的,可以理解為Global的。
- Process-specific型別的TLB:使用者地址空間是每個程序獨立的地址空間。prev程序切換到next程序時,TLB中快取的prev程序的相關資料對於next程序是無用的,因此可以沖刷掉,這就是所謂的process-specific的TLB。
ASID 最佳化
KPTI之前:
KPTI之後: