您的位置:首頁>正文

轟動整個電腦領域的晶片問題,究竟是怎麼回事?

在2017年年底的一個週末, 來自奧地利格拉茨技術大學的一名研究員寫出了一個程式, 成功的從作業系統中最受保護的地方獲取了自己網頁流覽和私人郵件資訊。 由於這個漏洞源於晶片設計本身, 他和他的同事們次日便將這個消息郵件告知了英特爾公司。 一個星期後他們收到了英特爾公司的回復。 原來他們已經不是第一個找到這個漏洞的人, 而英特爾公司也已經在著手修復。 為了不給駭客攻擊的機會, 雙方答應了延緩這個發現的發表, 直到新年伊始。

2018年1月2日, 論文發表, 英特爾、AMD和ARM的晶片同時被爆出安全問題。

總結來說, 這個晶片設計漏洞能夠引起兩種網路駭客攻擊, 分別是“崩潰(meltdown)”和“幽靈(spectre)”。

○ 英特爾晶片設計漏洞可能引起兩種網路駭客攻擊, 分別是“崩潰”和“幽靈”。

“崩潰”是一種打破應用程式與作業系統之間隔離的攻擊。 在崩潰攻擊下,

軟體就可以直接存取權限外的記憶體, 從而調取其他應用程式和系統資源;“幽靈”則是一種打破不同應用程式之間隔離的攻擊。 它可以讓駭客進行偽裝, 騙過系統的檢測, 最終達到調取資源的目的。

這意味著什麼呢?這意味著只要用電腦, 理論上都可能受到安全攻擊。 而且這個安全問題是根植在晶片的架構裡, 除非重新設計作業系統或者晶片, 否則這個問題無法從根本上得到解決。 而一切的原因, 都源自於我們幾十年來過於追求CPU的性能。

自從馮諾依曼在1945年提出了電腦架構至今的70多年的時間裡, 電腦的發展一直都基於這種架構。 除了在電晶體層面上的發展, 電腦架構師們也一直想方設法在架構上做文章, 使程式運行更快。

其中被沿用至今的包括多級儲存(memory hierarchy)、亂序執行(out-of-order execution)和推測執行(speculative execution)。

多級儲存:

首先來說說多級儲存。 如上圖所示, 簡單來說儲存從離CPU由遠到近可分為硬碟(Disk)、記憶體(RAM)、緩存(cache)和寄存器(register)。 儲存大小和讀取時間都是硬碟最大, 然後依次遞減。 現在的電腦一般有512GB或者1TB容量的硬碟,

16G或者8G的記憶體, 以及幾到十幾MB左右的緩存。 在這三級的儲存中只有硬碟是非易失性記憶(non-volatile memory)。 也就是說只有硬碟在電腦斷電之後仍能儲存資料。 因此, 我們平常需要的所有東西(啟動程式除外)都儲存在硬碟裡。 開機之後由啟動程式開啟作業系統, 由作業系統將需要的資料從硬碟移到記憶體。 而緩存的設計則是為了CPU能夠更快的讀取平時所需要的資料。

試想一下, 假如你正在寫一篇論文, 需要在圖書館查找資料。 你會把所需要的各種書從不同的書架上取下來放在桌上, 然後再從中選一兩本寫當下章節需要常看的書放在手邊以便隨時翻閱。 電腦架構的設計也遵從了這樣一個原則。 如果你是一個CPU,

那麼圖書館就是硬碟, 放書所用的桌子就是記憶體, 而你手邊觸手能即的地方就是緩存。 而當你離開圖書館的時候, 桌上和你手邊的書也會被管理員清空並放回原本的書架上。 由此可見, 多級儲存的設計目的就在於能讓CPU能夠儘量頻繁的 “在觸手可及的地方拿到需要的書”。

亂序執行:

再來說說亂序執行。 所有程式最終都會被拆分成一條條的指令, 由CPU逐個執行。 然而每條指令所花的時間並不相同, 比如你去圖書館書架上取書花的時間肯定比從手邊拿書要長。 最初的架構設計是讓CPU按程式順序依次逐個執行指令。 然而這就出現了一個新的問題, 如果一個指令需要花很長時間來執行(通常因為該指令沒有獲得足夠多的執行資源), 那麼後面指令(無論再簡單,需要花的時間再少)也必須等這條指令執行完之後才能開始執行。這就像在一條很窄的路上行車,如果前面有一輛車出了故障走不了,在這輛故障車等拖車來的這段時間裡,後面的車也只好堵著。當然現實生活中我們基本不會遇到這樣的情景。如果一輛車出了問題,它通常會靠邊停車,在打雙閃等拖車的同時,讓後面的車能夠順利通過。而後來電腦架構的設計也遵從了這一理念。如果一條指令需要花很長時間才能完成執行,那麼這條指令會被放到一個特殊的地方(reservation station),以便讓CPU能夠執行之後的指令。只有當放在reservation station的指令獲得足夠多資源執行的時候,該指令才會重新被執行。這就是被用在如今幾乎所有晶片裡的技術—亂序執行。

推測執行:

最後再來看看推測執行。假設你每晚放學必須要和你的朋友一起去吃個宵夜。你們通常都會去城東的燒烤店吃燒烤。當然,如果燒烤店人滿為患,你們也會選擇城北邊的炸雞店。那麼問題來了,放學的時候你怎麼知道燒烤店是否還有位子呢?當然你可以打電話去問,但是老闆通常很忙,打個電話得等個20分鐘才有回復。那麼放學後的你現在應該何去何從呢?現在你之前的經驗起了作用。如果你之前百分之八十的時候去燒烤店都是有座位的,那麼你在放學打電話的這20分鐘時間裡,你完全可以在接到答覆之前先往燒烤店走著,反正有百分之八十的機會你不用折返去城北。而整套機制放在電腦裡就是推測執行。在CPU執行指令的時候通常都會遇到判定,如果判定為真則執行一部分代碼,如果判定為偽,則執行另一段代碼。而通常判定是需要等待很長時間。而現在的CPU都會根據之前的控制流預測判定的結果,在結果確定之前,CPU會執行預測結果指向的指令。如果預測對了,那麼CPU則節省了等待判定結果的時間。如果預測錯了,則CPU會從開始判定的位置重新接受新的,正確的指令。雖然倒回原點重新執行新的指令會比較耗時,但是如果之前預測的準確性很高,比如90%,那麼這個結果還是可以接受的,畢竟總體上來說CPU執行指令還是省了不少時間。

上述三個架構上的技巧大大提高了CPU執行指令的效率。究其原理,主要就是使CPU能一直有事可做,不至於在那裡空轉浪費時間。然而,正是這三個幾乎現在所有CPU都有的特性,導致了這次晶片安全性能的滑鐵盧。在瞭解具體情況之前,我們還要瞭解一個作業系統的重要特性。

無論是什麼作業系統都會在兩個級別下運行,一個是用戶級別(user mode),一個是系統級別(kernel mode)。而使用者級別的優先順序會低於系統級別。也就是說系統級別的資源在使用者級別下是不能使用讀取的。這樣設置的原因是防止用戶讀取他不應該讀取的資訊,比如其他使用者的密碼。例如在程式的某個地方使用者試圖讀取其許可權外的資料,系統會自動從使用者級別跳到系統級別,然後阻止使用者讀取該資料。這就像你要進別人家的門,但是密碼輸入錯誤,門是會自動鎖住,不讓你進。

然而亂序執行和推測執行改變了這一切。從根本上說,亂序執行可以暫時跳過一些指令直接執行後面的指令。而推測執行時,錯誤的推測可能讓CPU直接執行一些許可權外的指令。這就像你能在輸入的門禁密碼得到判定前先進別人家逛一圈,等密碼判定為錯,再請你出去,然後鎖門。

從電腦架構上來看,如之前所述,電腦需要的資料都會提前存儲在記憶體中以供讀取。如果我們故意製造一個非法的資料訪問,因為該操作訪問了超過許可權的記憶體,操作理應會被拒絕。然而因為亂序執行和推測執行的存在,這些非法操作可以在還沒有被拒絕前執行。雖然最後這些非法操作最終會被系統拒絕並忽略(不對系統狀態造成影響),但這些已執行過的非法訪問的資料會因為多級儲存的架構而留在緩存上面。通過簡單的技術手段就可以反復推出真實的敏感性資料。也就是說你輸入的密碼因為晶片的內部設計,可以被其他使用者級別的程式直接獲取。這就好比在圖書館有一列書架上的書是不允許學生借閱的,但因為圖書管理員允許在身份確認前進入借閱,作為學生的你可以先進去把需要的書拿出來放到你的桌上。即使管理員最後確認了你的學生身份,禁止了你的許可權,但這個時候你需要的書已經被拿了出來放在了你的桌上。即便你不主動去讀,我們也不能阻止其他人偷偷去翻閱這本書。

所幸的是各大晶片公司對此早就在內部有了未公開的研究,爆出該問題的論文也是在各大公司有了更新和應對措施之後才被公之於眾。各個公司都發佈了自己的系統更新用於緩解該問題的嚴重性。但是值得注意的是,目前的補救辦法只能通過作業系統的補丁來修復。而這些補丁會對晶片的性能帶來從5%到30%不等的下降。而作業系統級別的修復只能緩解卻不能被徹底解決這個安全問題,除非重新設計晶片結構或者作業系統。

從馮諾依曼架構確定至今的幾十年時間裡,我們似乎因為太在意晶片的性能而開發出了很多諸如上述的提高晶片運行效率的技術。然而被我們忽略的硬體級別的安全性卻是隱藏在這下面更重要的特性。正所謂企者不立,跨者不行, 一味注重晶片性能的開發方式似乎走到了盡頭。而更加根本的馮諾依曼架構是否還能按照之前的腳步繼續發展,似乎也值得晶片架構師們深思。

那麼後面指令(無論再簡單,需要花的時間再少)也必須等這條指令執行完之後才能開始執行。這就像在一條很窄的路上行車,如果前面有一輛車出了故障走不了,在這輛故障車等拖車來的這段時間裡,後面的車也只好堵著。當然現實生活中我們基本不會遇到這樣的情景。如果一輛車出了問題,它通常會靠邊停車,在打雙閃等拖車的同時,讓後面的車能夠順利通過。而後來電腦架構的設計也遵從了這一理念。如果一條指令需要花很長時間才能完成執行,那麼這條指令會被放到一個特殊的地方(reservation station),以便讓CPU能夠執行之後的指令。只有當放在reservation station的指令獲得足夠多資源執行的時候,該指令才會重新被執行。這就是被用在如今幾乎所有晶片裡的技術—亂序執行。

推測執行:

最後再來看看推測執行。假設你每晚放學必須要和你的朋友一起去吃個宵夜。你們通常都會去城東的燒烤店吃燒烤。當然,如果燒烤店人滿為患,你們也會選擇城北邊的炸雞店。那麼問題來了,放學的時候你怎麼知道燒烤店是否還有位子呢?當然你可以打電話去問,但是老闆通常很忙,打個電話得等個20分鐘才有回復。那麼放學後的你現在應該何去何從呢?現在你之前的經驗起了作用。如果你之前百分之八十的時候去燒烤店都是有座位的,那麼你在放學打電話的這20分鐘時間裡,你完全可以在接到答覆之前先往燒烤店走著,反正有百分之八十的機會你不用折返去城北。而整套機制放在電腦裡就是推測執行。在CPU執行指令的時候通常都會遇到判定,如果判定為真則執行一部分代碼,如果判定為偽,則執行另一段代碼。而通常判定是需要等待很長時間。而現在的CPU都會根據之前的控制流預測判定的結果,在結果確定之前,CPU會執行預測結果指向的指令。如果預測對了,那麼CPU則節省了等待判定結果的時間。如果預測錯了,則CPU會從開始判定的位置重新接受新的,正確的指令。雖然倒回原點重新執行新的指令會比較耗時,但是如果之前預測的準確性很高,比如90%,那麼這個結果還是可以接受的,畢竟總體上來說CPU執行指令還是省了不少時間。

上述三個架構上的技巧大大提高了CPU執行指令的效率。究其原理,主要就是使CPU能一直有事可做,不至於在那裡空轉浪費時間。然而,正是這三個幾乎現在所有CPU都有的特性,導致了這次晶片安全性能的滑鐵盧。在瞭解具體情況之前,我們還要瞭解一個作業系統的重要特性。

無論是什麼作業系統都會在兩個級別下運行,一個是用戶級別(user mode),一個是系統級別(kernel mode)。而使用者級別的優先順序會低於系統級別。也就是說系統級別的資源在使用者級別下是不能使用讀取的。這樣設置的原因是防止用戶讀取他不應該讀取的資訊,比如其他使用者的密碼。例如在程式的某個地方使用者試圖讀取其許可權外的資料,系統會自動從使用者級別跳到系統級別,然後阻止使用者讀取該資料。這就像你要進別人家的門,但是密碼輸入錯誤,門是會自動鎖住,不讓你進。

然而亂序執行和推測執行改變了這一切。從根本上說,亂序執行可以暫時跳過一些指令直接執行後面的指令。而推測執行時,錯誤的推測可能讓CPU直接執行一些許可權外的指令。這就像你能在輸入的門禁密碼得到判定前先進別人家逛一圈,等密碼判定為錯,再請你出去,然後鎖門。

從電腦架構上來看,如之前所述,電腦需要的資料都會提前存儲在記憶體中以供讀取。如果我們故意製造一個非法的資料訪問,因為該操作訪問了超過許可權的記憶體,操作理應會被拒絕。然而因為亂序執行和推測執行的存在,這些非法操作可以在還沒有被拒絕前執行。雖然最後這些非法操作最終會被系統拒絕並忽略(不對系統狀態造成影響),但這些已執行過的非法訪問的資料會因為多級儲存的架構而留在緩存上面。通過簡單的技術手段就可以反復推出真實的敏感性資料。也就是說你輸入的密碼因為晶片的內部設計,可以被其他使用者級別的程式直接獲取。這就好比在圖書館有一列書架上的書是不允許學生借閱的,但因為圖書管理員允許在身份確認前進入借閱,作為學生的你可以先進去把需要的書拿出來放到你的桌上。即使管理員最後確認了你的學生身份,禁止了你的許可權,但這個時候你需要的書已經被拿了出來放在了你的桌上。即便你不主動去讀,我們也不能阻止其他人偷偷去翻閱這本書。

所幸的是各大晶片公司對此早就在內部有了未公開的研究,爆出該問題的論文也是在各大公司有了更新和應對措施之後才被公之於眾。各個公司都發佈了自己的系統更新用於緩解該問題的嚴重性。但是值得注意的是,目前的補救辦法只能通過作業系統的補丁來修復。而這些補丁會對晶片的性能帶來從5%到30%不等的下降。而作業系統級別的修復只能緩解卻不能被徹底解決這個安全問題,除非重新設計晶片結構或者作業系統。

從馮諾依曼架構確定至今的幾十年時間裡,我們似乎因為太在意晶片的性能而開發出了很多諸如上述的提高晶片運行效率的技術。然而被我們忽略的硬體級別的安全性卻是隱藏在這下面更重要的特性。正所謂企者不立,跨者不行, 一味注重晶片性能的開發方式似乎走到了盡頭。而更加根本的馮諾依曼架構是否還能按照之前的腳步繼續發展,似乎也值得晶片架構師們深思。

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示