Re: [情報] Intel嚴重漏洞 OS更新將會降低效能
看板PC_Shopping作者jk21234 (BL2400PT真不錯)時間6年前 (2018/01/06 00:20)推噓43(43推 0噓 32→)留言75則, 50人參與討論串35/38 (看更多)
為什麼cache預料之外的hit會導致data外流....
其實表面來說 資料沒有被讀出來 但是是被窮舉的方式猜出來的
基本原理
0. int64 a = rdtsc()
RDTSC = Read the Time Stamp Counter,
這個數字從開機的時候就從0開始增加,一個cycle + 1.
這個指令不用進入高權限模式就可以執行
Pentium 75開始就有,在1995之後大量被使用
來測試效能 或者是作速度控制.
導致為了相容性不容易把它拔掉或者禁止低權限模式使用
有些範例會用進階的rdtscp(),這個是修正版本
需要SSE2,但是跟多核心cpu相容...RDTSC在多核心cpu的值
不一樣,本用途則差異不大
int64 a = rdtsc()
b = load_mem(ADR_A)
a = rdtsc() - a
這時候a會相近於這次load_mem所花掉的cycle數,
有一些誤差 但是通常在10 cycle以下
如果我做兩次 一次得到的a是> 200 , 一次是 < 20,
對cpu有點了解的就知道,cpu有一種叫做cache的機制
讓讀取有些時候可以加快不用那麼慢
所以很直覺的, >200 應該表示cache miss , 原本不在cache中,
< 20 , 上次應該就在cache中
這個後面會應用到
<======想按左鍵嗎??
1. 假設已知CPU的最後一層Cache 有10MB, 而且為12-way,
如果我有一個陣列U[10MB].考慮最簡單的情況
我連續讀取這10MB之後那一瞬間,是不是會把cache中原本的資料幾乎
全部洗出來,cache中幾乎全部是我這10MB的資料.
是的 這是基本假設
然後我們進階一點,cache被U[10MB]塞滿之後 我再load_mem(A),
這時候因為cache沒有他的資料,一定是cache miss,然後放棄掉U[10MB]中的
某區塊不在cache中,下次就是這個區塊的記憶體萬一又要讀取到 就會miss
(中間省略)最後針對一個Address A,我都可以在U中找到32Byte*12
總共384Byte的位址 只要這群資料用12個load_mem()讀入,就會
保證Address A的資料被擠出Cache
Q1:所以要先知道cpu cache的大小跟規格???
A:不用 用前面的方法本身就可以探索出cpu cache的最大值
跟way-associative的數值,其實就是拿各種size的陣列U
讀取跟分割讀取,可以求到的數值
2.
a = rdtsc()
b = load_mem(SYSTEM_A)
a = rdtsc() - a
會發生甚麼事情?如果SYSTEM_A是一個猜的Address,位在保護區段且不可讀取
其實正常就是產生General Protection Fault,但可以Program自己接手回來
這個Exception
正常來說, B不會被更新, 但關鍵在第二次的rdtsc()甚麼時候執行
Out of order 有可能
a. load_mem之前
b. load_mem之後,exception之前
c. exception之後
第一種情況會得到一個特小個位數的值 也可以用mem_barrier()
或者mem_fence() (這兩種指令是規定指令與mem_load要排隊)
隔離開 第一種情況基本上就不會發生
第二種情況 驚異的是它很接近一般的mem_load,有時候可以看到
> 200t, 有時候看到 < 20t,明明SYSTEM_A就不給讀取...
第三種就是rdtsc會超長,1000cycle內不太可能,或者.多核心之下不一定正常
可以當雜訊值排除
不是用這個方法 但是繼續進化的話...
3.設定一個陣列X,可以是256 Byte,或者適當的倍數
然後我同樣有個U[10MB]的陣列
a = rdtsc()
b = load_mem(SYSTEM_A)
c = load_mem(&X + b)
mem_fense()
a = rdtsc() - a
第一次做無效的SYSTEM_A的load, B不會得到結果
但是,我這端不知道B的值 可是CPU知道X陣列的第B個元素
加起來是多少,他去載入這個位置了.....會在C拿到嗎
不會 第一次load_mem無效,第二次load_mem一樣無效
至於exception的問題同前,但是多跑幾次在這組行為中看到cache miss
與cache hit的時間差異
然後我找個樣本
a = rdtsc()
b = load_mem(DUMMY)
c = load_mem(&X + 0)
mem_fense()
a = rdtsc() - a
找出U[10MB]之中,對第二次&X + 0
具有cache互斥性的384 Byte資料為一組
抽出來 跟
a = rdtsc()
b = load_mem(SYSTEM_A)
c = load_mem(&X + B)
mem_fense()
a = rdtsc() - a
一起玩
如果發現&X + B的載入行為,Cache Miss的時間
和&X + 0的對照組相同
那麼, B的內容就是0
如果比照起來不相似&X + 0與它的384 byte伙伴的相處關係
那就要再找&X + 1,這時候是另外384 byte快樂伙伴
來比較.....最多比較256次來確定一個Byte
實際上這整個流程都在窮舉 應該全速運作也要十萬個cycle以上
才能確定1 Byte的資料
3a.Speculative Execution
我不太確定正確的方法要不要應用speculative execution的指令
在這件事情需要用被動的指令speculativity還是主動指定為
speculative execution 但假設是的話 可以應用的範圍為
無效的mem_load,原本會產生exception,
但是我可以用speculative execution,放在不會執行的if-else中
但CPU不具有足夠條件做出正確的branch prediction的話,
在不執行那端的mem_load也會排入pipeline,並且在最後取消
volatile V = *Y
a = rdtsc()
if (V > 0)
else
{
b = load_mem(DUMMY)
c = load_mem(&X + 0)
}
a = rdtsc() - a
==>speculative execution化
volatile V = *Y
a = rdtsc()
SPEC_TRUE(V) { }
SPEC_FALSE(V)
{
b = load_mem(DUMMY)
c = load_mem(&X + 0)
}
a = rdtsc() - a
這時候CPU ooo會同時開始執行SPEC_TRUE與SPEC_FALSE的指令
最後SPEC_FALSE因為不成立,所以load_mem執行到中間就被取消
但這中間已經去Memory動作了 因此Cache也產生變化,但是取消
後不發exception,可能速度會加快很多 然後Host OS無法
偵測到你一直在產生GPF,降低被發現的機率
F.最後結論
以上的用法有需多前提條件 因此了解這個條件後有對應的話
可能可以避開.....對這沒甚麼自信 降低發生問題的洞
1.電腦Cache讀取的時間與外部記憶體差異巨大
現況一定是這樣 未來也一定是 無解
2.rdtsc精確度太高 來個1000 cycle誤差就行
或者限制僅kernel mode可以用(規格上已經支援 但為了相容性不開)
總之rdtsc要背太多舊程式相容性的鍋..
3.直覺上,跑一個記憶體載入指令,應該要在合法的位置才啟動啊
但實際上:
|TLB/PF |VALID|
|FETCH|DECODE|MEM-----|ADR |WRITE|
為了加速,計算Address合法性要經過TLB不比Memory回來快上多少
因此在檢查的同時也發出了Memory 存取的功能,讓兩個一起發動
如果指令在MEM之前能檢查完Address的合法性 連整個
MEM/Cache Stage都不啟動的話則降低這種事情被分析跟被窮舉的可能
4.上面的例子等於一個指令中有Indirect Memory的存取.但沒有支援
這種指令的RISC並沒有完全避掉問題 所以單一指令有沒有MEM[MEM[ADR]]
這樣的存取能力是不是重點就不知道了
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.243.156.56
※ 文章網址: https://www.ptt.cc/bbs/PC_Shopping/M.1515169257.A.E56.html
推
01/06 00:25,
6年前
, 1F
01/06 00:25, 1F
推
01/06 00:25,
6年前
, 2F
01/06 00:25, 2F
推
01/06 00:29,
6年前
, 3F
01/06 00:29, 3F
→
01/06 00:30,
6年前
, 4F
01/06 00:30, 4F
推
01/06 00:35,
6年前
, 5F
01/06 00:35, 5F
推
01/06 00:41,
6年前
, 6F
01/06 00:41, 6F
→
01/06 00:43,
6年前
, 7F
01/06 00:43, 7F
→
01/06 00:45,
6年前
, 8F
01/06 00:45, 8F
→
01/06 00:45,
6年前
, 9F
01/06 00:45, 9F
推
01/06 00:49,
6年前
, 10F
01/06 00:49, 10F
推
01/06 01:00,
6年前
, 11F
01/06 01:00, 11F
推
01/06 01:06,
6年前
, 12F
01/06 01:06, 12F
推
01/06 01:09,
6年前
, 13F
01/06 01:09, 13F
推
01/06 01:24,
6年前
, 14F
01/06 01:24, 14F
推
01/06 01:43,
6年前
, 15F
01/06 01:43, 15F
推
01/06 01:48,
6年前
, 16F
01/06 01:48, 16F
推
01/06 01:59,
6年前
, 17F
01/06 01:59, 17F
推
01/06 02:20,
6年前
, 18F
01/06 02:20, 18F
推
01/06 02:25,
6年前
, 19F
01/06 02:25, 19F
→
01/06 02:28,
6年前
, 20F
01/06 02:28, 20F
→
01/06 02:28,
6年前
, 21F
01/06 02:28, 21F
推
01/06 02:29,
6年前
, 22F
01/06 02:29, 22F
→
01/06 02:30,
6年前
, 23F
01/06 02:30, 23F
推
01/06 02:34,
6年前
, 24F
01/06 02:34, 24F
推
01/06 02:36,
6年前
, 25F
01/06 02:36, 25F
→
01/06 02:39,
6年前
, 26F
01/06 02:39, 26F
→
01/06 02:39,
6年前
, 27F
01/06 02:39, 27F
→
01/06 02:39,
6年前
, 28F
01/06 02:39, 28F
→
01/06 02:40,
6年前
, 29F
01/06 02:40, 29F
→
01/06 02:45,
6年前
, 30F
01/06 02:45, 30F
推
01/06 03:23,
6年前
, 31F
01/06 03:23, 31F
→
01/06 03:31,
6年前
, 32F
01/06 03:31, 32F
推
01/06 03:44,
6年前
, 33F
01/06 03:44, 33F
→
01/06 03:44,
6年前
, 34F
01/06 03:44, 34F
→
01/06 03:44,
6年前
, 35F
01/06 03:44, 35F
推
01/06 04:03,
6年前
, 36F
01/06 04:03, 36F
推
01/06 04:13,
6年前
, 37F
01/06 04:13, 37F
推
01/06 04:58,
6年前
, 38F
01/06 04:58, 38F
→
01/06 07:04,
6年前
, 39F
01/06 07:04, 39F
→
01/06 07:05,
6年前
, 40F
01/06 07:05, 40F
推
01/06 07:05,
6年前
, 41F
01/06 07:05, 41F
→
01/06 07:07,
6年前
, 42F
01/06 07:07, 42F
推
01/06 08:01,
6年前
, 43F
01/06 08:01, 43F
推
01/06 08:14,
6年前
, 44F
01/06 08:14, 44F
→
01/06 08:27,
6年前
, 45F
01/06 08:27, 45F
推
01/06 09:24,
6年前
, 46F
01/06 09:24, 46F
推
01/06 09:32,
6年前
, 47F
01/06 09:32, 47F
推
01/06 10:18,
6年前
, 48F
01/06 10:18, 48F
推
01/06 11:22,
6年前
, 49F
01/06 11:22, 49F
推
01/06 11:49,
6年前
, 50F
01/06 11:49, 50F
推
01/06 13:12,
6年前
, 51F
01/06 13:12, 51F
→
01/06 13:12,
6年前
, 52F
01/06 13:12, 52F
→
01/06 13:12,
6年前
, 53F
01/06 13:12, 53F
→
01/06 13:22,
6年前
, 54F
01/06 13:22, 54F
推
01/06 13:46,
6年前
, 55F
01/06 13:46, 55F
推
01/06 14:42,
6年前
, 56F
01/06 14:42, 56F
→
01/06 14:43,
6年前
, 57F
01/06 14:43, 57F
→
01/06 14:46,
6年前
, 58F
01/06 14:46, 58F
→
01/06 14:48,
6年前
, 59F
01/06 14:48, 59F
→
01/06 14:49,
6年前
, 60F
01/06 14:49, 60F
→
01/06 14:49,
6年前
, 61F
01/06 14:49, 61F
→
01/06 14:52,
6年前
, 62F
01/06 14:52, 62F
→
01/06 14:55,
6年前
, 63F
01/06 14:55, 63F
→
01/06 14:56,
6年前
, 64F
01/06 14:56, 64F
→
01/06 14:58,
6年前
, 65F
01/06 14:58, 65F
推
01/06 15:01,
6年前
, 66F
01/06 15:01, 66F
推
01/06 16:53,
6年前
, 67F
01/06 16:53, 67F
推
01/06 22:01,
6年前
, 68F
01/06 22:01, 68F
→
01/06 23:00,
6年前
, 69F
01/06 23:00, 69F
推
01/07 00:52,
6年前
, 70F
01/07 00:52, 70F
推
01/07 01:00,
6年前
, 71F
01/07 01:00, 71F
推
01/07 04:57,
6年前
, 72F
01/07 04:57, 72F
推
01/11 11:36,
6年前
, 73F
01/11 11:36, 73F
推
01/11 14:58,
6年前
, 74F
01/11 14:58, 74F
推
02/06 13:22,
6年前
, 75F
02/06 13:22, 75F
討論串 (同標題文章)
完整討論串 (本文為第 35 之 38 篇):