一、摘要
最近,基于硬件的攻擊已經(jīng)開始通過Rowhammer內(nèi)存漏洞或旁路地址空間布局隨機(jī)化保護(hù)機(jī)制來攻擊系統(tǒng)了,這些攻擊方式都是基于處理器的內(nèi)存管理單元(MMU)與頁表的交互交互方式的。這些攻擊通常需要重復(fù)加載頁表,以觀察目標(biāo)系統(tǒng)行為的變化情況。為了提高M(jìn)MU的頁表查找速度,現(xiàn)代處理器都使用了多級緩存,例如轉(zhuǎn)譯查找緩存(translation lookaside buffers,TLB)、專用頁表緩存,甚至通用數(shù)據(jù)緩存。要想攻擊得手,需要在訪問頁表之前可靠地刷新這些緩存。為了從非特權(quán)進(jìn)程中刷新這些緩存,攻擊者需要基于這些緩存的內(nèi)部體系結(jié)構(gòu)、大小以及緩存交互方式來創(chuàng)建專門的內(nèi)存訪問模式。雖然關(guān)于TLB和數(shù)據(jù)高速緩存的信息通常都會在供應(yīng)商的處理器手冊中發(fā)布,但是關(guān)于不同處理器上的頁表高速緩存的特性方面的信息卻鮮有提及。在本文中,我們改進(jìn)了最近提出的針對MMU的EVICT + TIME攻擊,對來自Intel、ARM和AMD的20種不同微架構(gòu)中頁表緩存與其他緩存的內(nèi)部架構(gòu),大小以及其交互方式。同時,我們以代碼庫的形式將我們的發(fā)現(xiàn)公之于眾,該代碼庫不僅提供了一個方便的接口來刷新這些緩存,同時還可以用來在新的體系結(jié)構(gòu)上自動逆向頁表緩存。
二、引言
由于添加到系統(tǒng)中的高級防御日益增加,致使針對軟件的攻擊的難度也是與日俱增,因此,針對硬件的攻擊反而成為一種更有吸引力的替代方案。在這些攻擊也是五花八門,既有利于Rowhammer漏洞攻擊系統(tǒng)的,也有使用旁路攻擊破壞地址空間布局隨機(jī)化來泄漏加密密鑰的,甚至還有用來跟蹤鼠標(biāo)移動的。
在這些針對硬件的攻擊中,有許多攻擊都是通過濫用現(xiàn)代處理器與內(nèi)存來實現(xiàn)的。目前,所有的處理器的核心都是存儲器管理單元(MMU),它通過在多個進(jìn)程之間提供虛擬化內(nèi)存來簡化可用物理存儲器的管理工作。MMU使用稱為頁表的數(shù)據(jù)結(jié)構(gòu)來執(zhí)行虛擬存儲器到物理存儲器之間的轉(zhuǎn)換。頁表是基于硬件的攻擊的目標(biāo)所在。例如,由Rowhammer漏洞導(dǎo)致的頁表頁中的單個位翻轉(zhuǎn),將會授予攻擊者某種訪問權(quán)限來訪問本來無法訪問的物理內(nèi)存,從而進(jìn)一步獲得超級用戶權(quán)限。此外,諸如ASLR和其他使用ASLR引導(dǎo)的安全防御機(jī)制都依賴于代碼或數(shù)據(jù)都是被隨機(jī)存儲到虛擬存內(nèi)存中這一特性的。由于這個(秘密)信息被嵌入在頁表中,攻擊者可以利用MMU與頁表的交互方式進(jìn)行旁路攻擊,以獲取這些機(jī)密信息。
從虛擬內(nèi)存到物理內(nèi)存的轉(zhuǎn)換通常會很慢,因為它需要進(jìn)行多次內(nèi)存訪問來解析原始虛擬地址。為了提高性能,現(xiàn)代處理器都使用多級緩存,例如轉(zhuǎn)譯查找緩存(TLB)、專用頁表緩存,甚至通用數(shù)據(jù)緩存。為了成功攻擊頁表,攻擊者經(jīng)常需要重復(fù)刷新這些緩存,以觀察系統(tǒng)在處理頁表時的行為。通過參閱處理器手冊,人們可以很容易找到TLB和數(shù)據(jù)高速緩存的各種詳細(xì)信息。然而,關(guān)于頁表緩存的信息,例如它們的大小和行為,通常是很難找到的。因為沒有這些信息,攻擊者需要借助于試錯法,所以,如果他們要想打造可以適用于多種體系結(jié)構(gòu)上的攻擊的話,難度可想而知。
在本文中,我們對現(xiàn)有的AnC進(jìn)行了重大的升級改造。AnC是一種針對MMU的EVICT + TIME旁路攻擊,它能夠?qū)ntel、ARM和AMD等公司的20多種微架構(gòu)的處理器的頁表緩存的大小、內(nèi)部體系結(jié)構(gòu)以及它們與其他緩存的交互方式進(jìn)行逆向。AnC依賴于以下事實:MMU查找的頁表將被存儲在最后一級高速緩存(LLC)中,以供下一次查找時使用,從而提高地址轉(zhuǎn)換速度。通過刷新LLC的部分內(nèi)容和對頁表查找進(jìn)行定時,AnC可以識別出LLC的哪些部分是用來存儲頁表的。除了刷新LLC,AnC還需要刷新TLB以及頁表緩存。由于有關(guān)TLB和LLC的大小的信息是可知的,所以攻擊者可以使用AnC來逆向自己感興趣的頁表緩存的特性,如其內(nèi)部結(jié)構(gòu)和大小等。
簡而言之,我們做出了以下貢獻(xiàn):
我們描述了一種新技術(shù),可以用來對現(xiàn)代處理器中非常常見卻無文檔說明的頁表緩存進(jìn)行逆向工程。
我們利用Intel、ARM和AMD的20種不同微結(jié)構(gòu)處理器對我們的技術(shù)進(jìn)行了深入評估。
我們以開源軟件的形式發(fā)布了用于刷新緩存的框架實現(xiàn)。我們實現(xiàn)的框架提供了一個方便的接口,可以方便地應(yīng)用于我們已經(jīng)測試的各種微架構(gòu)上,來刷新頁表緩存,并且它還可以用來自動檢測新處理器上的頁表緩存。更多信息,請訪問: https://www.vusec.net/projects/anc
三、、背景和動機(jī)
在本節(jié)中,我們討論分頁內(nèi)存管理機(jī)制和它在大多數(shù)現(xiàn)代處理器上的實現(xiàn)。此外,我們還將考察MMU是如何進(jìn)行虛擬地址轉(zhuǎn)換的,以及用于提高這種轉(zhuǎn)換性能的各種緩存。
1. 頁式技術(shù)和MMU
頁面技術(shù)已經(jīng)成為現(xiàn)代處理器架構(gòu)的一個組成部分,因為它能夠通過虛擬化技術(shù)來簡化物理內(nèi)存的管理:由于地址空間有限,操作系統(tǒng)不再需要重新分配應(yīng)用程序的整個內(nèi)存,并且不再需要處理物理內(nèi)存碎片。此外,操作系統(tǒng)可以限制進(jìn)程訪問的內(nèi)存空間,防止惡意代碼或故障代碼干擾其他進(jìn)程。
它所帶來的直接后果,就是許多現(xiàn)代處理器架構(gòu)都采用了MMU,一個負(fù)責(zé)將虛擬地址轉(zhuǎn)換為相應(yīng)物理地址的硬件組件。轉(zhuǎn)換信息被存儲在頁表中——一種多級單向樹,每個級別都可以由虛擬地址的一部分進(jìn)行索引,從而選擇下一級頁表,或者在葉級別,也就是物理頁面。因此,每個虛擬地址都能夠從樹的根節(jié)點到葉節(jié)點唯一地選出一條路徑以找到對應(yīng)的物理地址。
圖1詳細(xì)展示了MMU是如何在x86_64上執(zhí)行虛擬地址轉(zhuǎn)換的。首先,MMU讀取CR3寄存器以找到頂級頁表的物理地址。然后,用虛擬地址的前9位作為索引在該頁表中選擇頁表項(PTE)。這個PTE包含對下一級頁表的引用,然后用虛擬地址中接下來9位的作為索引繼續(xù)選擇頁表項。通過對下兩個級別重復(fù)該操作,MMU就可以在最低級頁表中找到對應(yīng)于0x644b321f4000的物理頁了。
圖1:在x86_64架構(gòu)上,將0x644b321f4000轉(zhuǎn)換成其對應(yīng)的內(nèi)存頁的MMU的頁表查詢過程。
2. 緩存MMU的操作
如果MMU可以避免從頭開始解析其最近已解析過的虛擬地址的話,那么內(nèi)存的訪問性能就會得到極大的改善。為此,CPU會將解析過的地址映射存儲到TLB高速緩存中。因此,如果在TLB中命中的話,就無需查詢各個頁表了,而這個過程是需要花費許多時間的。此外,為了提高TLB未命中時的性能,處理器會將頁表數(shù)據(jù)存儲到數(shù)據(jù)高速緩存中。
現(xiàn)代處理器還可以進(jìn)一步提高TLB未命中情況下的地址轉(zhuǎn)換性能,方法是使用頁表緩存或轉(zhuǎn)譯緩存來緩存不同級別頁表的PTE。雖然頁表緩存使用物理地址和PTE索引進(jìn)行索引,但是轉(zhuǎn)換緩存使用的是已經(jīng)過部分解析的虛擬地址。通過轉(zhuǎn)譯緩存,MMU可以查找虛擬地址并選擇具有最長匹配前綴的頁表,即選擇存在于給定虛擬地址的高速緩存內(nèi)的最低級頁表。雖然這允許MMU免去部分頁表的查詢工作,但是轉(zhuǎn)譯緩存的實現(xiàn)同時也帶來了額外的復(fù)雜性。
此外,這些高速緩存在實現(xiàn)方式也可以多種多樣,不僅可以實現(xiàn)多個專用的高速緩存供不同的頁表級使用,而且還可以實現(xiàn)單個高速緩存來供不同的頁表級共享,或者甚至可以作為一個可以緩存PTE的TLB來加以實現(xiàn)。例如,AMD的Page Walking Caches(就像在AMD K8和AMD K10微架構(gòu)中發(fā)現(xiàn)的那樣)采用的是統(tǒng)一頁表緩存的方式,而Intel的Page-Structure Caches的實現(xiàn)采用的是專用的轉(zhuǎn)譯緩存的方式。類似地,ARM在針對低功耗和硅利用率而優(yōu)化的設(shè)計中實現(xiàn)了統(tǒng)一的頁表緩存(頁表查詢緩存),同時它們在針對高性能而優(yōu)化的設(shè)計中實現(xiàn)了統(tǒng)一的轉(zhuǎn)換緩存(中間頁表查找緩存)。
圖2展示了當(dāng)MMU翻譯虛擬地址時不同高速緩存的交互方式。雖然TLB和緩存具有完整的文檔說明,但是關(guān)于頁表和翻譯緩存的諸多細(xì)節(jié)仍然缺乏相關(guān)的文檔說明。
圖2:MMU的通用實現(xiàn)以及將虛擬地址轉(zhuǎn)換為物理地址的所有組件。
3. 研究動機(jī)
最近的基于頁表濫用的硬件攻擊,都要求能夠正確刷新頁表緩存,才能完成相應(yīng)的操作。例如,預(yù)取攻擊依賴于一個正確的時機(jī),屆時虛擬地址轉(zhuǎn)換恰好在一個頁表緩存中部分成功,借以了解內(nèi)核中隨機(jī)化地址方面的信息。而Rowhammer攻擊在處理頁表時則需要重復(fù)刷新TLB和頁表緩存,以掃描物理內(nèi)存中的敏感信息
另一個需要刷新頁表緩存的例子是AnC攻擊。MMU的頁表查詢結(jié)果會被緩存到LLC中。AnC利用這個事實來完成FLUSH + RELOAD攻擊,以確定出MMU在頁表查詢期間訪問的頁表內(nèi)存頁中的偏移量。知道這個偏移量后,就能找到經(jīng)過隨機(jī)化處理后的虛擬地址,從而攻陷ASLR防御機(jī)制。但是,為了完成一次可靠的攻擊,AnC需要嘗試多種不同的訪問模式,并且每種模式都需要嘗試許多次,并且每次都需要有效地刷新頁表緩存以便觸發(fā)完整的頁表查詢流程。因此,關(guān)于頁表緩存的內(nèi)部工作機(jī)制的知識,對于完成正確高效的AnC攻擊來說是非常必要的。
在某些情況下,TLB用作頁表緩存。在這些情況下,cpuid指令可以用來了解不同TLB的大小,這樣就知道了不同頁表緩存的大小了。但是,在一些x86_64微體系結(jié)構(gòu)上,cpuid指令并不會給出所有TLB的大小。例如,盡管在Intel Sandy Bridge和Ivy Bridge處理器上存在可以緩存1 GB頁面的TLB,但這些信息根本無法通過cpuid指令獲取。此外,在其他CPU體系結(jié)構(gòu)上,可能沒有辦法獲取TLB的大小,或者頁表緩存可能已經(jīng)實現(xiàn)為完全獨立的單元。因此,我們需要一個更通用的方法來探索頁表緩存的重要屬性。
四、頁表緩存逆向技術(shù)
我們現(xiàn)在開始討論如何改造AnC技術(shù),以探測頁表緩存的各種屬性。實際上,我們需要克服許多挑戰(zhàn),才能使AnC適用于不同的架構(gòu),這些將在后面展開詳細(xì)的討論。
1. 使用MMU的緩存信號
代碼清單1:設(shè)計原理示意代碼
在了解頁表緩存時,我們依賴于這樣一個事實,即MMU的頁表查詢結(jié)束于目標(biāo)處理器的數(shù)據(jù)緩存處。下面以Intel x86 64為例進(jìn)行說明,這里假設(shè)使用了四個頁表級別,那么給定虛擬地址v的MMU的頁表查詢會將來自4個頁表內(nèi)存頁的4個緩存行放入L1數(shù)據(jù)緩存以及L3,假設(shè)L3包括L1。這樣一來,如果高速緩存行仍然位于數(shù)據(jù)緩中的話,那么再次對虛擬地址v進(jìn)行頁面查詢的時候,就會變得相當(dāng)快。
CPU數(shù)據(jù)緩存被分為不同的緩存集。每個緩存組可以存儲多達(dá)N個緩存行,這被稱為N路組相關(guān)緩存。Oren等人發(fā)現(xiàn),給定兩個不同的(物理)內(nèi)存頁面,如果它們的第一個緩存行屬于同一緩存組,那么頁面中的其他緩存行也會共享(不同的)緩存組,即如果我們在一個與緩存行邊界對齊的頁面內(nèi)選擇了偏移t,那么另一內(nèi)存頁中的偏移t處的緩存行就會共享相同的緩存組。這是因為:為了讓兩個內(nèi)存頁的第一個緩存行位于同一個緩存組中,那么決定緩存組和切片(slice)的兩個頁面的物理地址的所有位必須是相同的,并且兩個頁面內(nèi)的偏移將共享相同的低位。
利用緩存的這個特性,我們可以輕松利用一些內(nèi)存頁來用作驅(qū)逐緩沖區(qū)。假設(shè)用于轉(zhuǎn)換虛擬地址v的四個頁表項中的一個正好位于頁表內(nèi)存頁的偏移零處。當(dāng)我們訪問驅(qū)逐緩沖區(qū)中所有頁面的第一個緩存行的時候,我們將從緩存中驅(qū)逐掉MMU的最近轉(zhuǎn)換虛擬地址v時的頁表查詢結(jié)果。因此,虛擬地址v的下一次頁表查詢將會變得稍微慢一些,因為它需要從內(nèi)存獲取前面提到過的頁表項。這就是一個EVICT + TIME攻擊的例子,通過它,AnC就能夠在存儲頁表項的內(nèi)存頁面中,從潛在的64個緩存行中找出4個緩存行。注意,通過嘗試來自虛擬地址v之外的各種偏移,我們可以弄清楚每個級別中的頁表項對應(yīng)于哪些緩存行中。例如,如果我們在v + 32 KB上執(zhí)行EVICT + TIME,與在v上執(zhí)行EVICT + TIME時相比發(fā)生變化的緩存行對應(yīng)于級別1頁表的緩存行。
這是因為在x86 64架構(gòu)上,每個緩存行可以存儲8個頁表項,映射32 KB的虛擬內(nèi)存。
假設(shè)一個頁表緩存對應(yīng)于一個頁表級別,若不刷新該級別的頁表緩存的話,我們就無法觀察MMU在該級別上的活動。舉例來說,假設(shè)有一個頁表緩存,它用來緩存具有32個表項的2級頁表。假設(shè)2級頁表中的每個表項可以映射2 MB的虛擬內(nèi)存,當(dāng)我們訪問連續(xù)的64 MB虛擬緩沖區(qū)(以2MB為邊界)的時候,我們將刷新該頁表緩存。因此,我們可以輕松地通過蠻力方式窮舉每個級別的潛在頁表緩存的大小。例如,如果在x86 64架構(gòu)的Intel處理器上我們無法通過AnC觀察到上面三級頁表的信號,那是因為該頁面(轉(zhuǎn)譯)緩存位于2級頁表中。然后,我們可以蠻力破解該緩存的大小,然后移動到上一級。代碼清單1為我們展示了具體的實現(xiàn)過程。注意,與AnC不同,我們采用了一個已知的虛擬地址,所以我們可以準(zhǔn)確知道MMU信號應(yīng)該出現(xiàn)在緩存中的什么地方。當(dāng)然,為了提高清單1中代碼的魯棒性,使其適用于多種處理器架構(gòu),我們還需要解決許多問題,具體將在后文中詳細(xì)展開。
2. 確保存取順序
許多現(xiàn)代CPU架構(gòu)都實現(xiàn)了亂序執(zhí)行技術(shù),其中指令的執(zhí)行順序取決于輸入數(shù)據(jù)的可用性,而不是它們在原始程序中的順序。在應(yīng)用亂序執(zhí)行技術(shù)之后,指令在解碼之后被插入等待隊列中,直到它們的輸入操作數(shù)可用為止。一旦輸入操作數(shù)可用,該指令就會被發(fā)送到相應(yīng)的執(zhí)行單元,這樣的話,這條指令就會先于前面的指令由該單元執(zhí)行了。此外,這種CPU架構(gòu)通常都是超標(biāo)量的,因為它們具有多個執(zhí)行單元,并且允許將多條指令調(diào)度到這些不同的執(zhí)行單元中并行執(zhí)行。在指令執(zhí)行完成之后,它們的結(jié)果將被寫入另一個現(xiàn)已“退休的”隊列中,該隊列以原始程序的順序進(jìn)行排序,以保證正確的邏輯順序。此外,有些現(xiàn)代CPU架構(gòu)不僅具有針對指令的亂序執(zhí)行的能力,而且它們還具有對內(nèi)存操作進(jìn)行重新排序的能力。為了測量這種CPU體系結(jié)構(gòu)上單個指令的執(zhí)行時間,我們必須在定時指令之前和之后注入內(nèi)存屏障,并目標(biāo)代碼之前和之后插入代碼屏障,以清除正在運行的指令和內(nèi)存操作。為了串行化內(nèi)存存取順序,我們可以在ARMv7-A和ARMv8-A上面使用dsb指令,而在x86_64上,可以通過rdtscp和mfence指令保證串行化的內(nèi)存存取順序。為了串行化指令順序,我們可以在x86_64上使用cpuid指令,在ARMv7-A和ARMv8-A上使用isb sy指令。
3. 定時
在緩存命中和緩存未命中的情況下,存在從幾百納秒或甚至幾十納秒的性能差異,因此我們需要高精度的定時源才能能夠區(qū)分緩存是否命中。雖然在兼容POSIX的操作系統(tǒng)上可以通過clock_gettime()來獲取定時信息,但是在各種ARMv7-A和ARMv8-A平臺上,它們提高的定時信息卻不夠精確。
許多現(xiàn)代處理器架構(gòu)都提供了專用寄存器來計數(shù)處理器的周期數(shù),從而提供高精度的定時源。雖然這些寄存器可通過各種rdtscp指令中的非特權(quán)rdtsc進(jìn)行訪問,但默認(rèn)情況下,ARMv7-A和ARMv8-A上的性能監(jiān)視單元(PMU)提供的PMCCNTR寄存器是無法訪問的。此外,當(dāng)最初引入這些寄存器時,沒有確保它們在內(nèi)核之間是同步的,并且直接利用處理器時鐘使其計數(shù)進(jìn)行遞增。在這些情況下,進(jìn)程遷移和動態(tài)頻率調(diào)整會對定時造成一定程度的影響,甚至讓它變得不再可靠。
考慮到當(dāng)今大多數(shù)處理器都具有多個內(nèi)核,在循環(huán)中簡單遞增全局變量的線程可以提供一個基于軟件的周期計數(shù)器。我們發(fā)現(xiàn)這種方法在各種平臺上都能夠可靠地工作,并且可以提供很高的精度度。請注意,JavaScript版本的AnC也采用了類似的技術(shù)來構(gòu)建高精度的計時器。
4. 討論
利用x86_64平臺上的cpuid以及ARMv7-A和ARMv8-A上的扁平設(shè)備樹(FDT),我們可以檢測包括處理器屬性(如TLB、緩存、處理器和供應(yīng)商的名稱)和微架構(gòu)的等處理器拓?fù)湫畔ⅰS辛诉@些信息,我們就可以構(gòu)建一個適當(dāng)?shù)尿?qū)逐組,以便在缺少頁表和轉(zhuǎn)譯緩存的架構(gòu)上成功地自動執(zhí)行AnC攻擊。因此,在帶有頁表或轉(zhuǎn)譯緩存的體系結(jié)構(gòu)上,我們可以通過構(gòu)建驅(qū)逐組并嘗試漸進(jìn)式執(zhí)行AnC攻擊來逆向這些緩存的大小。
五、評測
我們使用Intel、ARM和AMD等公司從2008年到2016年期間發(fā)布的20個不同的CPU對我們的技術(shù)進(jìn)行了全面的評估,并發(fā)現(xiàn)了每個頁表級的頁表緩存的具體大小(我們稱2級頁表為PL2),以及利用我們的技術(shù)逆向這個信息所需要的時間。同時,我們還提供了每種CPU的緩存和TLB的大小。
我們的研究結(jié)果總結(jié)見表1。下面,我們將逐一介紹各個供應(yīng)商產(chǎn)品在這些方面的特點和差異。
表1:22種不同微架構(gòu)的規(guī)格和逆向結(jié)果
1. Intel
在英特爾的處理器中,最后一級緩存是包含型的,這意味著最后一級緩存中可用的數(shù)據(jù)必須在較低級別的緩存中可用。由于這個特性,只要從最后一級緩存中逐出緩存行就足夠了,因為這將導(dǎo)致它們將被從較低級別的緩存中逐出。我們發(fā)現(xiàn),英特爾的頁面結(jié)構(gòu)緩存或切片轉(zhuǎn)譯緩存是在Intel Core和Xeon處理器上實現(xiàn)的,至少是Nehalem微架構(gòu)。在Intel Core和Xeon處理器上,具有可供24-32個PL2表項和4-6個PL3表項的高速緩存,而在Silvermont處理器上,只有一個高速緩存,僅僅可以供12-16個PL2表項使用。在我們的多次測試期間,我們注意到,它們主要集中于幾個彼此接近的數(shù)字。保守的攻擊者可以總是選擇更大的數(shù)字。在Intel Core和Xeon處理器以及Silvermont處理器上,我們發(fā)現(xiàn)cpuid報告的TLB的大小正好適用于完全刷新這些緩存,這很可能是因為用于緩存巨型頁面的TLB也包含了緩存中間頁面查詢的邏輯。最后,我們發(fā)現(xiàn),當(dāng)Sandy Bridge和Ivy Bridge實現(xiàn)一個TLB來緩存1G頁面時,cpuid指令不會報告這個TLB的存在,并且Nehalem和Westmere都實現(xiàn)了一個PL3頁面結(jié)構(gòu)緩存,但是沒有提供這樣的TLB實現(xiàn)。
2. AMD
在AMD的處理器上,LLC是獨占型的,這意味著數(shù)據(jù)最多可以放入一個高速緩存中,以便可以一次存儲更多的數(shù)據(jù)。為了能夠正確驅(qū)逐緩存行,我們必須分配一個驅(qū)逐組,其大小等于高速緩存大小的總和。我們經(jīng)測試發(fā)現(xiàn),AMD K10微體系結(jié)構(gòu)實現(xiàn)了AMD的頁面查詢緩存具有24個表項。此外,我們的測試表明,AMD的頁面查詢緩存沒有被Bulldozer微體系結(jié)構(gòu)的設(shè)計和該微體系結(jié)構(gòu)的后代所采用。因此,AMD的Bulldozer架構(gòu)似乎沒有提供任何頁表或轉(zhuǎn)譯緩存。
最后,AMD的Bobcat架構(gòu)似乎實現(xiàn)了一個帶有8到12個表項的頁面目錄緩存。
3. ARMv7-A
與Intel和AMD的處理器不同,根據(jù)片上系統(tǒng)的供應(yīng)商的不同,有些ARM處理器上的L2緩存可以配置為包含型、獨占型或非包含型。
然而,對于大多數(shù)ARMv7-A處理器來說,這些緩存都是配置為非包含型的。在ARMv7-A上,有兩個頁面級別可用,其中的頁表分別提供256和4096個表項,分別可以映射4K和1M空間。對于支持大容量物理內(nèi)存地址擴(kuò)展(LPAE)的處理器,則使用三個頁面級別,其中每個頁表分別提供了512、512和4個表項,可以映射4K、1M和1G空間。即使最后一級頁表僅由適合單個緩存行的四個表項組成,但是AnC攻擊仍然可以應(yīng)用于其他兩個頁面級別,以確定頁表和轉(zhuǎn)譯緩存的存在性。此外,其低功耗版本(例如ARM Cortex A7)則實現(xiàn)了統(tǒng)一的頁表緩存,而面向高性能的版本(例如ARM Cortex A15和A17)則實現(xiàn)了統(tǒng)一的轉(zhuǎn)譯緩存。但是,較舊的設(shè)計,如ARM Cortex A8和A9,卻根本沒有任何MMU緩存。同時,我們發(fā)現(xiàn)帶有64個表項的頁表緩存和帶有16個表項的轉(zhuǎn)譯緩存分別可用于ARM Cortex A7和ARM Cortex A15。此外,我們的程序可以可靠地確定出所有支持和不支持LPAE的ARMv7-A的這些高速緩存的大小,即使在啟用所有核心的ARM big.LITTLE處理器上,也可以透明地在不同類型的核心之間來回切換。
4. ARMv8-A
ARMv8-A處理器也實現(xiàn)了類似于Intel和AMD的包含型LLC。此外,ARMv8-A使用與x86_64類似的模型,提供了四個頁面級別,每級512個表項。然而,在Linux系統(tǒng)上,僅使用了三個頁面級別來提高頁表查找的性能。與ARMv7-A類似,ARMv8-A在其低功耗版本(例如ARM Cortex A53)上實現(xiàn)了4路關(guān)聯(lián)64項統(tǒng)一頁表緩存,并在注重性能的版本,例如ARM Cortex A57, A72和A73中實現(xiàn)了一個統(tǒng)一的轉(zhuǎn)譯緩存。此外,我們還發(fā)現(xiàn)ARM Cortex A53實現(xiàn)了一個具有64個表項的頁表緩存。
5. 討論
如代碼清單2所示,我們可以通過分配與緩存項一樣多的頁面,然后“觸動”每個頁面級別中的每個頁面來刷新TLB和頁面結(jié)構(gòu)。通過觸動這些頁面,MMU就會被迫執(zhí)行虛擬地址轉(zhuǎn)換以替換緩存中的現(xiàn)有的表項。此外,通過使用頁面大小作為每個頁面級別的步幅,我們可以利用巨型頁面來刷新頁面結(jié)構(gòu)緩存或TLB。
1 /* Flush the TLBs and page structure caches. */
2 for (j = 0, level = fmt->levels; j <= page_level; ++level, ++j)
3 {
4 p = cache->data + cache_line * cache->line_size;
5 6
for (i = 0; i < level->ncache_entries; ++i) {
7 *p = 0x5A;
8 p += level->page_size;
9 }
10 }
代碼清單2:刷新TLB和頁面結(jié)構(gòu)緩存。
六、相關(guān)工作
1. 針對頁表的硬件攻擊
AnC攻擊可以根據(jù)MMU將PTE緩存到LLC中的方式來發(fā)動EVICT + TIME攻擊,從而利用JavaScript給用戶空間ASLR去隨機(jī)化。而使用預(yù)取指令的硬件攻擊則依賴于緩存的TLB表項和部分轉(zhuǎn)譯來實現(xiàn)內(nèi)核空間ASLR的去隨機(jī)化。頁表是Rowhammer攻擊最有吸引力的目標(biāo)。Drammer和Seaborn的硬件攻擊會破壞PTE,使其指向頁表頁面。但是,如果不能正確刷新頁表緩存的話,所有這些攻擊都將失敗。本文提供了一種用于在各種體系結(jié)構(gòu)上刷新這些緩存的通用技術(shù)。
2. 逆向硬件
針對商品化硬件的逆向工程已經(jīng)隨著對硬件的攻擊的增加而變得日益流行。Hund等人對英特爾處理器如何將物理內(nèi)存地址映射到LLC進(jìn)行了逆向工程。Maurice 等人則使用性能計數(shù)器來簡化了該映射功能的逆向過程。DRAMA則使用DRAM總線的被動探測以及對DRAM行緩沖器的定時攻擊,對內(nèi)存控制器將數(shù)據(jù)放置在DRAM模塊上的原理進(jìn)行了逆向工程。在本文中,我們對現(xiàn)有處理器的MMU中常見的頁表緩存的各種未公開的特性進(jìn)行了相應(yīng)的逆向工程。
七、結(jié)束語
當(dāng)前,基于硬件的攻擊(如緩存或Rowhammer攻擊)開始變得越來越流行,因為針對軟件的攻擊已經(jīng)變得越來越具有挑戰(zhàn)性。對于跨處理器的魯棒性攻擊方法來說,掌握各種處理器內(nèi)緩存的相關(guān)特性是至關(guān)重要的。由于這些緩存通常對軟件來說是不可見的,因此通常很難找到相關(guān)的文檔說明。在本文中,我們改進(jìn)了針對MMU的現(xiàn)有EVICT + TIME攻擊,使其能夠逆向最新處理器上常見的頁表緩存的各種特性。我們將該技術(shù)應(yīng)用于20個不同的微架構(gòu),發(fā)現(xiàn)其中17個實現(xiàn)了這樣的頁表緩存。我們的開源實現(xiàn)提供了一個便利的接口,可以用于在這16個微體系結(jié)構(gòu)上刷新這些緩存,并可以在未來的微架構(gòu)上自動檢測頁表緩存。更多信息,請訪問: https://www.vusec.net/projects/anc