Re: [情報] Intel嚴重漏洞 OS更新將會降低效能

看板PC_Shopping作者 (BL2400PT真不錯)時間6年前 (2018/01/06 00:20), 編輯推噓43(43032)
留言75則, 50人參與, 6年前最新討論串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
JK神
01/06 00:30, 4F

01/06 00:35, 6年前 , 5F
JK最高
01/06 00:35, 5F

01/06 00:41, 6年前 , 6F
推 JK 神
01/06 00:41, 6F

01/06 00:43, 6年前 , 7F
3的描述有bug, X要是256 Byte的很多倍而且&X + 0
01/06 00:43, 7F

01/06 00:45, 6年前 , 8F
該知道我簡化過不想修正回來了..
01/06 00:45, 8F

01/06 00:45, 6年前 , 9F
jk神!先推再說
01/06 00:45, 9F

01/06 00:49, 6年前 , 10F
好久沒推 先推再說
01/06 00:49, 10F

01/06 01:00, 6年前 , 11F
推jk神
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
這個理組也不一定看得懂好嗎XD
01/06 01:59, 17F

01/06 02:20, 6年前 , 18F
看不懂,推
01/06 02:20, 18F

01/06 02:25, 6年前 , 19F
推,我開始覺得我4年CS白唸了QQ
01/06 02:25, 19F

01/06 02:28, 6年前 , 20F
我大二計算機結構交作業就是用rdtsc提供cpu cache
01/06 02:28, 20F

01/06 02:28, 6年前 , 21F
資料
01/06 02:28, 21F

01/06 02:29, 6年前 , 22F
比較好奇這麼久的bug 怎麼會到現在才被找出來?
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
推 Archi / OS 都快忘光了 QQ
01/06 02:36, 25F

01/06 02:39, 6年前 , 26F
想出2的例子的是好幾年前就有但這樣只能分析系統虛
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
直到3的例子成立才會變資料能被分析走
01/06 02:40, 29F

01/06 02:45, 6年前 , 30F
所以是Intel挖坑自己跳
01/06 02:45, 30F

01/06 03:23, 6年前 , 31F
RDTSC本來就不該讓低權限的APP使用,CPUID也是
01/06 03:23, 31F

01/06 03:31, 6年前 , 32F
難怪有人說X86是個爛架構
01/06 03:31, 32F

01/06 03:44, 6年前 , 33F
剛剛查了一下資料,RDTSC指令是可以禁止在CPL=3執
01/06 03:44, 33F

01/06 03:44, 6年前 , 34F
行的,其實只要OS把這個指令禁止掉所有的問題不都
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
感覺一直以來x86為相容性付出的成本太大了
01/06 04:13, 37F

01/06 04:58, 6年前 , 38F
01/06 04:58, 38F

01/06 07:04, 6年前 , 39F
mem[mem[a+b]可以直接一條執行代表btb一猜錯馬上有
01/06 07:04, 39F

01/06 07:05, 6年前 , 40F
cache資料洩漏問題,包括in order cpu
01/06 07:05, 40F

01/06 07:05, 6年前 , 41F
推了表示懂
01/06 07:05, 41F

01/06 07:07, 6年前 , 42F
像clflush是cpl3可跑但wbinvd 只有cpl0可跑也蠻怪
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
感謝分享,又更了解一些了! 這應該能拿到CS課堂上講
01/06 11:22, 49F

01/06 11:49, 6年前 , 50F
略懂略懂 可是電蝦點在?( 被毆
01/06 11:49, 50F

01/06 13:12, 6年前 , 51F
其實跟x86沒有關係 純粹是為了快略過檢查導致這個漏
01/06 13:12, 51F

01/06 13:12, 6年前 , 52F
洞 不然x86的amd沒這個問題 risc的arm和A系列晶片有
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
最主要是cache的演算法問題
01/06 14:42, 56F

01/06 14:43, 6年前 , 57F
不管是x86 ARM powerpc 或是各種DSP RISC
01/06 14:43, 57F

01/06 14:46, 6年前 , 58F
cache 演算法不外乎就是random , round robin 之類
01/06 14:46, 58F

01/06 14:48, 6年前 , 59F
因為ASIC成本考量大部分人不可能實作一個很複雜的
01/06 14:48, 59F

01/06 14:49, 6年前 , 60F
演算法去增加那1~5%效能或是安全性check
01/06 14:49, 60F

01/06 14:49, 6年前 , 61F
最有效簡單的方式就是一個夠大夠快fetch的cache
01/06 14:49, 61F

01/06 14:52, 6年前 , 62F
用指令架構上的做法確保cache的安全性是合乎邏輯的
01/06 14:52, 62F

01/06 14:55, 6年前 , 63F
AMD跟ARM這次不受災的原因在於他們很早就用比較新的
01/06 14:55, 63F

01/06 14:56, 6年前 , 64F
演算法去處理cache coherence的問題
01/06 14:56, 64F

01/06 14:58, 6年前 , 65F
intel工程師睡了很久。
01/06 14:58, 65F

01/06 15:01, 6年前 , 66F
若是相信陰謀論的話這個印該是intel故意不修復的
01/06 15:01, 66F

01/06 16:53, 6年前 , 67F
資管系路過 到2就看不太懂了zz
01/06 16:53, 67F

01/06 22:01, 6年前 , 68F
理工組推 (前3行都看DER懂)
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
文章代碼(AID): #1QJwNfvM (PC_Shopping)
討論串 (同標題文章)
完整討論串 (本文為第 35 之 38 篇):
文章代碼(AID): #1QJwNfvM (PC_Shopping)