centos
一個攻擊輪由三個階段。在第一階段中,被監控的內存的映射從cache中被剔除,在第三階段以前,間諜進程容許目標訪問內存。在第三階段,間諜進程從新載入內存行,測量從新載入的時間。若是在等待的階段,目標進程訪問了指定的內存空間,那麼這個內存的空間就在cache中有記錄,重載就只須要很短的時間。另外一方面,若是目標沒有訪問指定的內存空間,則這個空間就須要從內存中提取,重載話費更長的時間。圖3(a)和(b)分別顯示了無目標進程訪問和有目標進程訪問的時間線。緩存
如圖3(c)所示,目標進程訪問可能和間諜的重載階段重疊,在這種狀況下,目標進程訪問不會觸發緩存的填充。相反,目標進程會使用重載階段的緩存數據。所以,間諜進程就錯過了訪問機會。相似的,也發生在部分覆蓋的狀況。就像圖3(D),重載發生在目標進程訪問數據時。因爲目標進程和間諜進程代碼執行是無關的,所以增長等待的時間能夠減小因爲重疊而丟失訪問的機率。另外一方面,增長等待的時間也削弱了攻擊的粒度。測試
提升攻擊分辨率而不增長錯誤率的方法的就是提升針對指定區域提升訪問速率,例如使用循環體。攻擊沒法區分不一樣訪問,可是,如圖3(e),丟失的概率很小。優化
因爲目標進程的處理器的內存入口隨機化,多處理器優化可能出現錯誤。這些優化包括數據的預提取以開闢空間和亂序執行。在分析攻擊結果的時候,攻擊着必須意識到優化和發展,並過濾他們的影響。咱們的攻擊代碼以下,這個代碼測量在內存地址讀取數據的時間,而後剔除cache中的內存的映射。這個測量使用內嵌彙編指令的方式執行。ui
int probe(char *adrs) { volatile unsigned long time; asm __volatile__ ( " mfence \n" " lfence \n" " rdtsc \n" " lfence \n" " movl %%eax, %%esi \n" " movl (%1), %%eax \n" " lfence \n" " rdtsc \n" " subl %%esi, %%eax \n" " clflush 0(%1) \n" : "=a" (time) : "c" (adrs) : "%esi", "%edx"); return time < threshold; }
彙編代碼須要一個輸入,地址,儲存在%ecx中(16行)。變量time是返回值,他是讀取%eax寄存器中地址儲存值的時間(15行)。第10行讀取%ecx中地址指向4個bytes,地址由adrs變量指向。spa
爲了測量這次讀取所須要的時間,咱們使用處理器的時間戳計數器。在第7行rdtsc指令讀取64位計數器,低32bits在%eax中,%edx中儲存高32bits。因爲咱們測量的時間很短,因此咱們只是用低位,忽略%edx中的高位。第9行將計數器複製到%ESI。讀取內存以後,再次調用,時間戳計數器(12行)。第13行,減去計數器的值,把結果放在寄存器%eax中。這個技術的關鍵是在cache中剔除指定的內存映射的能力。這個功能使用在14行中clflush這個指令。clflush指令能夠從全部的cache層次中剔除指定的內存映射,包括全部核心的L1層和L2層。剔除所核心的映射,確保下次目標進程被映射到L3層上。blog
mfence和ifence指令的做用是使指令連續化。處理器可能在執行指令的時候是並行化或者不按順序的。若是沒有連續化,指令可能被分割執行。lfence指令可使指令部分連續。他確保這個指令後面的指令不會在它以前執行。mfence指令做用於儲存操做。然而,他不針對其餘指令,沒法有效的分割。英特爾推薦使用cpuid進行指令串行化,然而,在虛擬化環境中,虛擬機管理器中cpuid仿真耗時過長(1000個週期以上),沒法提供攻擊所需的粒度。18行比較兩個rdtsc指令與預約閾值之間的時間差。應爲以前已經被清除了映射關係,若是返回的時間差小於閾值,則代表另外一個進程訪問了內存行,超過的話,則沒有訪問。進程
攻擊中閾值的選擇是依賴於系統,爲了找到測試系統的閾值,咱們使用代碼測試內存和L1緩存的加載時間(爲了測量L1的時間,咱們移除14行的clflush指令)。在centos6.5系統,HP Elite 8300電腦的測試,如圖5,電腦使用i5-3470處理器。內存
來自L1cache緩存的數據經歷了44個週期(注意,這裏包括了rdtsc和fence指令的執行時間,所以比單一指令時間更長)。從內存加載數據的時間,超過百分之98的時間在270到290個週期之間。其他分佈在880個週期,大約200個在1140到1175個週期。內存訪問,沒有小於200個時鐘週期。文檔
這個時間取決於硬件和軟件環境,戴爾PowerEdge T420,從L1載入須要33到43個,而內存須要230個週期,在相同的硬件條件下,使用KVM虛擬化,有百分之0.02從內存載入須要6000個週期。
基於測量結果和英特爾文檔,咱們將閾值設置爲120個週期。