|
在2017年年底的一個(gè)周末,來自奧地利格拉茨技術(shù)大學(xué)的一名研究員寫出了一個(gè)程序,成功的從操作系統(tǒng)中最受保護(hù)的地方獲取了自己網(wǎng)頁瀏覽和私人郵件信息。由于這個(gè)漏洞源于芯片設(shè)計(jì)本身,他和他的同事們次日便將這個(gè)消息郵件告知了英特爾公司。一個(gè)星期后他們收到了英特爾公司的回復(fù)。原來他們已經(jīng)不是第一個(gè)找到這個(gè)漏洞的人,而英特爾公司也已經(jīng)在著手修復(fù)。為了不給黑客攻擊的機(jī)會(huì),雙方答應(yīng)了延緩這個(gè)發(fā)現(xiàn)的發(fā)表,直到新年伊始。 2018年1月2日,論文發(fā)表,英特爾、AMD和ARM的芯片同時(shí)被爆出安全問題。總結(jié)來說,這個(gè)芯片設(shè)計(jì)漏洞能夠引起兩種網(wǎng)絡(luò)黑客攻擊,分別是“崩潰(meltdown)”和“幽靈(spectre)”。 ○ 英特爾芯片設(shè)計(jì)漏洞可能引起兩種網(wǎng)絡(luò)黑客攻擊,分別是“崩潰”和“幽靈”。 “崩潰”是一種打破應(yīng)用程序與操作系統(tǒng)之間隔離的攻擊。在崩潰攻擊下,軟件就可以直接訪問權(quán)限外的內(nèi)存,從而調(diào)取其他應(yīng)用程序和系統(tǒng)資源;“幽靈”則是一種打破不同應(yīng)用程序之間隔離的攻擊。它可以讓黑客進(jìn)行偽裝,騙過系統(tǒng)的檢測,最終達(dá)到調(diào)取資源的目的。 這意味著什么呢?這意味著只要用電腦,理論上都可能受到安全攻擊。而且這個(gè)安全問題是根植在芯片的架構(gòu)里,除非重新設(shè)計(jì)操作系統(tǒng)或者芯片,否則這個(gè)問題無法從根本上得到解決。而一切的原因,都源自于我們幾十年來過于追求CPU的性能。 計(jì)算機(jī)架構(gòu) 自從馮諾依曼在1945年提出了計(jì)算機(jī)架構(gòu)至今的70多年的時(shí)間里,計(jì)算機(jī)的發(fā)展一直都基于這種架構(gòu)。除了在晶體管層面上的發(fā)展,計(jì)算機(jī)架構(gòu)師們也一直想方設(shè)法在架構(gòu)上做文章,使程序運(yùn)行更快。其中被沿用至今的包括多級儲(chǔ)存(memory hierarchy)、亂序執(zhí)行(out-of-order execution)和推測執(zhí)行(speculative execution)。 多級儲(chǔ)存: 首先來說說多級儲(chǔ)存。如上圖所示,簡單來說儲(chǔ)存從離CPU由遠(yuǎn)到近可分為硬盤(Disk)、內(nèi)存(RAM)、緩存(cache)和寄存器(register)。儲(chǔ)存大小和讀取時(shí)間都是硬盤最大,然后依次遞減。現(xiàn)在的計(jì)算機(jī)一般有512GB或者1TB容量的硬盤,16G或者8G的內(nèi)存,以及幾到十幾MB左右的緩存。在這三級的儲(chǔ)存中只有硬盤是非易失性記憶(non-volatile memory)。也就是說只有硬盤在計(jì)算機(jī)斷電之后仍能儲(chǔ)存數(shù)據(jù)。因此,我們平常需要的所有東西(啟動(dòng)程序除外)都儲(chǔ)存在硬盤里。開機(jī)之后由啟動(dòng)程序開啟操作系統(tǒng),由操作系統(tǒng)將需要的數(shù)據(jù)從硬盤移到內(nèi)存。而緩存的設(shè)計(jì)則是為了CPU能夠更快的讀取平時(shí)所需要的數(shù)據(jù)。 試想一下,假如你正在寫一篇論文,需要在圖書館查找資料。你會(huì)把所需要的各種書從不同的書架上取下來放在桌上,然后再從中選一兩本寫當(dāng)下章節(jié)需要??吹臅旁谑诌呉员汶S時(shí)翻閱。計(jì)算機(jī)架構(gòu)的設(shè)計(jì)也遵從了這樣一個(gè)原則。如果你是一個(gè)CPU,那么圖書館就是硬盤,放書所用的桌子就是內(nèi)存,而你手邊觸手能即的地方就是緩存。而當(dāng)你離開圖書館的時(shí)候,桌上和你手邊的書也會(huì)被管理員清空并放回原本的書架上。由此可見,多級儲(chǔ)存的設(shè)計(jì)目的就在于能讓CPU能夠盡量頻繁的 “在觸手可及的地方拿到需要的書”。 亂序執(zhí)行: 再來說說亂序執(zhí)行。所有程序最終都會(huì)被拆分成一條條的指令,由CPU逐個(gè)執(zhí)行。然而每條指令所花的時(shí)間并不相同,比如你去圖書館書架上取書花的時(shí)間肯定比從手邊拿書要長。最初的架構(gòu)設(shè)計(jì)是讓CPU按程序順序依次逐個(gè)執(zhí)行指令。然而這就出現(xiàn)了一個(gè)新的問題,如果一個(gè)指令需要花很長時(shí)間來執(zhí)行(通常因?yàn)樵撝噶顩]有獲得足夠多的執(zhí)行資源),那么后面指令(無論再簡單,需要花的時(shí)間再少)也必須等這條指令執(zhí)行完之后才能開始執(zhí)行。這就像在一條很窄的路上行車,如果前面有一輛車出了故障走不了,在這輛故障車等拖車來的這段時(shí)間里,后面的車也只好堵著。當(dāng)然現(xiàn)實(shí)生活中我們基本不會(huì)遇到這樣的情景。如果一輛車出了問題,它通常會(huì)靠邊停車,在打雙閃等拖車的同時(shí),讓后面的車能夠順利通過。而后來計(jì)算機(jī)架構(gòu)的設(shè)計(jì)也遵從了這一理念。如果一條指令需要花很長時(shí)間才能完成執(zhí)行,那么這條指令會(huì)被放到一個(gè)特殊的地方(reservation station),以便讓CPU能夠執(zhí)行之后的指令。只有當(dāng)放在reservation station的指令獲得足夠多資源執(zhí)行的時(shí)候,該指令才會(huì)重新被執(zhí)行。這就是被用在如今幾乎所有芯片里的技術(shù)—亂序執(zhí)行。 推測執(zhí)行: 最后再來看看推測執(zhí)行。假設(shè)你每晚放學(xué)必須要和你的朋友一起去吃個(gè)宵夜。你們通常都會(huì)去城東的燒烤店吃燒烤。當(dāng)然,如果燒烤店人滿為患,你們也會(huì)選擇城北邊的炸雞店。那么問題來了,放學(xué)的時(shí)候你怎么知道燒烤店是否還有位子呢?當(dāng)然你可以打電話去問,但是老板通常很忙,打個(gè)電話得等個(gè)20分鐘才有回復(fù)。那么放學(xué)后的你現(xiàn)在應(yīng)該何去何從呢?現(xiàn)在你之前的經(jīng)驗(yàn)起了作用。如果你之前百分之八十的時(shí)候去燒烤店都是有座位的,那么你在放學(xué)打電話的這20分鐘時(shí)間里,你完全可以在接到答復(fù)之前先往燒烤店走著,反正有百分之八十的機(jī)會(huì)你不用折返去城北。而整套機(jī)制放在計(jì)算機(jī)里就是推測執(zhí)行。在CPU執(zhí)行指令的時(shí)候通常都會(huì)遇到判定,如果判定為真則執(zhí)行一部分代碼,如果判定為偽,則執(zhí)行另一段代碼。而通常判定是需要等待很長時(shí)間。而現(xiàn)在的CPU都會(huì)根據(jù)之前的控制流預(yù)測判定的結(jié)果,在結(jié)果確定之前,CPU會(huì)執(zhí)行預(yù)測結(jié)果指向的指令。如果預(yù)測對了,那么CPU則節(jié)省了等待判定結(jié)果的時(shí)間。如果預(yù)測錯(cuò)了,則CPU會(huì)從開始判定的位置重新接受新的,正確的指令。雖然倒回原點(diǎn)重新執(zhí)行新的指令會(huì)比較耗時(shí),但是如果之前預(yù)測的準(zhǔn)確性很高,比如90%,那么這個(gè)結(jié)果還是可以接受的,畢竟總體上來說CPU執(zhí)行指令還是省了不少時(shí)間。 上述三個(gè)架構(gòu)上的技巧大大提高了CPU執(zhí)行指令的效率。究其原理,主要就是使CPU能一直有事可做,不至于在那里空轉(zhuǎn)浪費(fèi)時(shí)間。然而,正是這三個(gè)幾乎現(xiàn)在所有CPU都有的特性,導(dǎo)致了這次芯片安全性能的滑鐵盧。在了解具體情況之前,我們還要了解一個(gè)操作系統(tǒng)的重要特性。 操作系統(tǒng)的特性 無論是什么操作系統(tǒng)都會(huì)在兩個(gè)級別下運(yùn)行,一個(gè)是用戶級別(user mode),一個(gè)是系統(tǒng)級別(kernel mode)。而用戶級別的優(yōu)先級會(huì)低于系統(tǒng)級別。也就是說系統(tǒng)級別的資源在用戶級別下是不能使用讀取的。這樣設(shè)置的原因是防止用戶讀取他不應(yīng)該讀取的信息,比如其他用戶的密碼。例如在程序的某個(gè)地方用戶試圖讀取其權(quán)限外的數(shù)據(jù),系統(tǒng)會(huì)自動(dòng)從用戶級別跳到系統(tǒng)級別,然后阻止用戶讀取該數(shù)據(jù)。這就像你要進(jìn)別人家的門,但是密碼輸入錯(cuò)誤,門是會(huì)自動(dòng)鎖住,不讓你進(jìn)。 然而亂序執(zhí)行和推測執(zhí)行改變了這一切。從根本上說,亂序執(zhí)行可以暫時(shí)跳過一些指令直接執(zhí)行后面的指令。而推測執(zhí)行時(shí),錯(cuò)誤的推測可能讓CPU直接執(zhí)行一些權(quán)限外的指令。這就像你能在輸入的門禁密碼得到判定前先進(jìn)別人家逛一圈,等密碼判定為錯(cuò),再請你出去,然后鎖門。 從計(jì)算機(jī)架構(gòu)上來看,如之前所述,計(jì)算機(jī)需要的數(shù)據(jù)都會(huì)提前存儲(chǔ)在內(nèi)存中以供讀取。如果我們故意制造一個(gè)非法的數(shù)據(jù)訪問,因?yàn)樵摬僮髟L問了超過權(quán)限的內(nèi)存,操作理應(yīng)會(huì)被拒絕。然而因?yàn)閬y序執(zhí)行和推測執(zhí)行的存在,這些非法操作可以在還沒有被拒絕前執(zhí)行。雖然最后這些非法操作最終會(huì)被系統(tǒng)拒絕并忽略(不對系統(tǒng)狀態(tài)造成影響),但這些已執(zhí)行過的非法訪問的數(shù)據(jù)會(huì)因?yàn)槎嗉墐?chǔ)存的架構(gòu)而留在緩存上面。通過簡單的技術(shù)手段就可以反復(fù)推出真實(shí)的敏感數(shù)據(jù)。也就是說你輸入的密碼因?yàn)樾酒膬?nèi)部設(shè)計(jì),可以被其他用戶級別的程序直接獲取。這就好比在圖書館有一列書架上的書是不允許學(xué)生借閱的,但因?yàn)閳D書管理員允許在身份確認(rèn)前進(jìn)入借閱,作為學(xué)生的你可以先進(jìn)去把需要的書拿出來放到你的桌上。即使管理員最后確認(rèn)了你的學(xué)生身份,禁止了你的權(quán)限,但這個(gè)時(shí)候你需要的書已經(jīng)被拿了出來放在了你的桌上。即便你不主動(dòng)去讀,我們也不能阻止其他人偷偷去翻閱這本書。 所幸的是各大芯片公司對此早就在內(nèi)部有了未公開的研究,爆出該問題的論文也是在各大公司有了更新和應(yīng)對措施之后才被公之于眾。各個(gè)公司都發(fā)布了自己的系統(tǒng)更新用于緩解該問題的嚴(yán)重性。但是值得注意的是,目前的補(bǔ)救辦法只能通過操作系統(tǒng)的補(bǔ)丁來修復(fù)。而這些補(bǔ)丁會(huì)對芯片的性能帶來從5%到30%不等的下降。而操作系統(tǒng)級別的修復(fù)只能緩解卻不能被徹底解決這個(gè)安全問題,除非重新設(shè)計(jì)芯片結(jié)構(gòu)或者操作系統(tǒng)。 從馮諾依曼架構(gòu)確定至今的幾十年時(shí)間里,我們似乎因?yàn)樘谝庑酒男阅芏_發(fā)出了很多諸如上述的提高芯片運(yùn)行效率的技術(shù)。然而被我們忽略的硬件級別的安全性卻是隱藏在這下面更重要的特性。正所謂企者不立,跨者不行, 一味注重芯片性能的開發(fā)方式似乎走到了盡頭。而更加根本的馮諾依曼架構(gòu)是否還能按照之前的腳步繼續(xù)發(fā)展,似乎也值得芯片架構(gòu)師們深思。
|
|
|