歡迎光臨
每天分享高質量文章

關於 Linux 頁面表隔離補丁的神秘情況 | Linux 中國

註意,這是一件相互之間高度相關的事件,因此,它的主要描述都是猜測,除非過一段時間,它的限制禁令被取消。我所看到的,包括涉及到的供應商、許多爭論和這種戲劇性場面,將在限制禁令取消的那一天出現。
— Python Sweetness


本文導航
編譯自 | http://pythonsweetness.tumblr.com/post/169166980422/the-mysterious-case-of-the-linux-page-table 
 作者 | Python Sweetness
 譯者 | qhwdw

本文勘誤與補充[1]

長文預警: 這是一個目前嚴格限制的、禁止披露的安全 bug(LCTT 譯註:目前已經部分披露),它影響到目前幾乎所有實現虛擬記憶體的 CPU 架構,需要硬體的改變才能完全解決這個 bug。通過軟體來緩解這種影響的緊急開發工作正在進行中,並且最近在 Linux 內核中已經得以實現,並且,在 11 月份,在 NT 內核中也開始了一個類似的緊急開發。在最糟糕的情況下,軟體修複會導致一般工作負載出現巨大的減速(LCTT 譯註:外在表現為 CPU 性能下降)。這裡有一個提示,攻擊會影響虛擬化環境,包括 Amazon EC2 和 Google 計算引擎,以及另外的提示是,這種精確的攻擊可能涉及一個新的 Rowhammer 變種(LCTT 譯註:一個由 Google 安全團隊提出的 DRAM 的安全漏洞,在文章的後面部分會簡單介紹)。

我一般不太關心安全問題,但是,對於這個 bug 我有點好奇,而一般會去寫這個主題的人似乎都很忙,要麼就是知道這個主題細節的人會保持沉默。這讓我在新年的第一天(元旦那天)花了幾個小時深入去挖掘關於這個謎團的更多信息,並且我將這些信息片斷拼湊到了一起。

註意,這是一件相互之間高度相關的事件,因此,它的主要描述都是猜測,除非過一段時間,它的限制禁令被取消。我所看到的,包括涉及到的供應商、許多爭論和這種戲劇性場面,將在限制禁令取消的那一天出現。

LWN

這個事件的線索出現於 12 月 20 日 LWN 上的 內核頁面表的當前狀況:頁面隔離[2]這篇文章。從文章語氣上明顯可以看到這項工作的緊急程度,內核的核心開發者緊急加入了 KAISER 補丁系列[3]的開發——它由奧地利的 TU Graz[4] 的一組研究人員首次發表於去年 10 月份。

這一系列的補丁的用途從概念上說很簡單:為了阻止運行在用戶空間的行程在行程頁面表中通過映射得到內核空間頁面的各種攻擊方式,它可以很好地阻止了從非特權的用戶空間代碼中識別到內核虛擬地址的攻擊企圖。

這個小組在描述 KAISER 的論文《KASLR 已死:KASLR 永存[5]》摘要中特別指出,當用戶代碼在 CPU 上處於活動狀態的時候,在記憶體管理硬體中刪除所有內核地址空間的信息。

這個補丁集的魅力在於它觸及到了核心,內核的全部基柱(以及與用戶空間的接口),顯然,它應該被最優先考慮。遍觀 Linux 中記憶體管理方面的變化,通常某個變化的首次引入會發生在該改變被合併的很久之前,並且,通常會進行多次的評估、拒絕、以及因各種原因爆發爭論的一系列過程。

而 KAISER(就是現在的 KPTI)系列(從引入到)被合併還不足三個月。

ASLR 概述

從錶面上看,這些補丁設計以確保地址空間佈局隨機化Address Space Layout Randomization(ASLR)仍然有效:這是一個現代操作系統的安全特性,它試圖將更多的隨機位引入到公共映射物件的地址空間中。

例如,在取用 /usr/bin/python 時,動態鏈接將對系統的 C 庫、堆、執行緒棧、以及主要的可執行檔案進行排布,去接受隨機分配的地址範圍:

  1. $ bash -c grep heap /proc/$$/maps

  2. 019de000-01acb000 rw-p 00000000 00:00 0                                  [heap]

  3. $ bash -c 'grep heap /proc/$$/maps’

  4. 023ac000-02499000 rw-p 00000000 00:00 0                                  [heap]

註意兩次運行的 bash 行程的堆(heap)的開始和結束偏移量上的變化。

如果一個快取區管理的 bug 將導致攻擊者可以去覆寫一些程式代碼指向的記憶體地址,而那個地址之後將在程式控制流中使用,這樣這種攻擊者就可以使控制流轉向到一個包含他們所選擇的內容的緩衝區上。而這個特性的作用是,對於攻擊者來說,使用機器代碼來填充緩衝區做他們想做的事情(例如,呼叫 system() C 庫函式)將更困難,因為那個函式的地址在不同的運行行程上不同的。

這是一個簡單的示例,ASLR 被設計用於去保護類似這樣的許多場景,包括阻止攻擊者瞭解有可能被用來修改控制流的程式資料的地址或者實現一個攻擊。

KASLR 是應用到內核本身的一個 “簡化的” ASLR:在每個重新引導的系統上,屬於內核的地址範圍是隨機的,這樣就使得,雖然被攻擊者操控的控制流運行在內核樣式上,但是,他們不能猜測到為實現他們的攻擊目的所需要的函式和結構的地址,比如,定位當前行程的資料段,將活動的 UID 從一個非特權用戶提升到 root 用戶,等等。

壞訊息:緩減這種攻擊的軟體運行成本過於貴重

之前的方式,Linux 將內核的記憶體映射到用戶記憶體的同一個頁面表中的主要原因是,當用戶的代碼觸發一個系統呼叫、故障、或者產生中斷時,就不需要改變正在運行的行程的虛擬記憶體佈局。

因為它不需要去改變虛擬記憶體佈局,進而也就不需要去清洗掉(flush)依賴於該佈局的與 CPU 性能高度相關的快取(LCTT 譯註:意即如果清掉這些高速快取,CPU 性能就會下降),而主要是通過 轉換查找緩衝器Translation Lookaside Buffer[6](TLB)(LCTT 譯註:TLB ,將虛擬地址轉換為物理地址)。

隨著頁面表分割補丁的合併,內核每次開始運行時,需要將內核的快取清掉,並且,每次用戶代碼恢復運行時都會這樣。對於大多數工作負載,在每個系統呼叫中,TLB 的實際總損失將導致明顯的變慢:@grsecurity 測量的一個簡單的案例[7],在一個最新的 AMD CPU 上,Linux du -s 命令變慢了 50%。

34C3

在今年的 CCC 大會上,你可以找到 TU Graz 的另外一位研究人員,《描述了一個純 Javascript 的 ASLR 攻擊[8]》,通過仔細地掌握 CPU 記憶體管理單元的操作時機,遍歷了描述虛擬記憶體佈局的頁面表,來實現 ASLR 攻擊。它通過高度精確的時間掌握和選擇性回收的 CPU 快取行的組合方式來實現這種結果,一個運行在 web 瀏覽器的 Javascript 程式可以找回一個 Javascript 物件的虛擬地址,使得可以利用瀏覽器記憶體管理 bug 進行接下來的攻擊。(LCTT 譯註:本文作者勘誤說,上述鏈接 CCC 的講演與 KAISER 補丁完全無關,是作者弄錯了)

因此,從錶面上看,我們有一組 KAISER 補丁,也展示瞭解除 ASLR 化地址的技術,並且,這個展示使用的是 Javascript,它很快就可以在一個操作系統內核上進行重新部署。

虛擬記憶體概述

在通常情況下,當一些機器碼嘗試去加載、儲存、或者跳轉到一個記憶體地址時,現代的 CPU 必須首先去轉換這個 虛擬地址 到一個 物理地址 ,這是通過遍歷一系列操作系統托管的陣列(被稱為頁面表)的方式進行的,這些陣列描述了虛擬地址和安裝在這台機器上的物理記憶體之間的映射。

在現代操作系統中,虛擬記憶體可能是最重要的強大特性:它可以避免什麼發生呢?例如,一個瀕臨死亡的行程崩潰了操作系統、一個 web 瀏覽器 bug 崩潰了你的桌面環境、或者一個運行在 Amazon EC2 中的虛擬機的變化影響了同一臺主機上的另一個虛擬機。

這種攻擊的原理是,利用 CPU 上維護的大量的快取,通過仔細地操縱這些快取的內容,它可以去推測記憶體管理單元的地址,以去訪問頁面表的不同層級,因為一個未快取的訪問將比一個快取的訪問花費更長的時間(以實時而言)。通過檢測頁面表上可訪問的元素,它可能能夠恢覆在 MMU(LCTT 譯註:儲存器管理單元)忙於解決的虛擬地址中的大部分比特(bits)。

這種動機的證據,但是不用恐慌

我們找到了動機,但是到目前為止,我們並沒有看到這項工作引進任何恐慌。總的來說,ASLR 並不能完全緩減這種風險,並且也是一道最後的防線:僅在這 6 個月的周期內,即便是一個沒有安全意識的人也能看到一些關於解除(unmasking) ASLR 化的指標的新聞,並且,實際上這種事從 ASLR 出現時就有了。

單獨的修複 ASLR 並不足於去描述這項工作高優先級背後的動機。

它是硬體安全 bug 的證據

通過閱讀這一系列補丁,可以明確許多事情。

第一,正如 @grsecurity 指出[9] 的,代碼中的一些註釋已經被編輯掉了(redacted),並且,描述這項工作的附加的主文件檔案已經在 Linux 原始碼樹中看不到了。

通過檢查代碼,它以運行時補丁的方式構建,在系統引導時僅當內核檢測到是受影響的系統時才會被應用,與對臭名昭著的 Pentium F00F bug[10] 的緩解措施,使用完全相同的機制:

更多的線索:Microsoft 也已經實現了頁面表的分割

通過對 FreeBSD 原始碼的一個簡單挖掘可以看出,目前,其它的自由操作系統沒有實現頁面表分割,但是,通過 Alex Ioniscu 在 Twitter[11] 上的提示,這項工作已經不局限於 Linux 了:從 11 月起,公開的 NT 內核也已經實現了同樣的技術。

猜測:Rowhammer

對 TU Graz 研究人員的工作的進一步挖掘,我們找到這篇 《當 rowhammer 僅敲一次[12]》,這是 12 月 4 日通告的一個 新的 Rowhammer 攻擊的變種[13]

在這篇論文中,我們提出了新的 Rowhammer 攻擊和漏洞的原始利用方式,表明即便是組合了所有防禦也沒有效果。我們的新攻擊技術,對一個位置的反覆 “敲打”(hammering),打破了以前假定的觸發 Rowhammer bug 的前提條件。

快速回顧一下,Rowhammer 是多數(全部?)種類的商業 DRAM 的一類根本性問題,比如,在普通的計算機中的記憶體上。通過精確操作記憶體中的一個區域,這可能會導致記憶體該區域儲存的相關(但是邏輯上是獨立的)內容被毀壞。效果是,Rowhammer 可能被用於去反轉記憶體中的比特(bits),使未經授權的用戶代碼可以訪問到,比如,這個比特位描述了系統中的其它代碼的訪問權限。

我發現在 Rowhammer 上,這項工作很有意思,尤其是它反轉的位接近頁面表分割補丁時,但是,因為 Rowhammer 攻擊要求一個標的:你必須知道你嘗試去反轉的比特在記憶體中的物理地址,並且,第一步是得到的物理地址可能是一個虛擬地址,就像在 KASLR 中的解除(unmasking)工作。

猜測:它影響主要的雲供應商

在我能看到的內核郵件串列中,除了該子系統維護者的名字之外,e-mail 地址屬於 Intel、Amazon 和 Google 的雇員,這表示這兩個大的雲計算供應商對此特別感興趣,這為我們提供了一個強大的線索,這項工作很大的可能是受虛擬化安全驅動的。

它可能會導致產生更多的猜測:虛擬機 RAM 和由這些虛擬機所使用的虛擬記憶體地址,最終表示為在主機上大量的相鄰的陣列,那些陣列,尤其是在一個主機上只有兩個租戶的情況下,在 Xen 和 Linux 內核中是通過記憶體分配來確定的,這樣可能會有(準確性)非常高的可預測行為。

最喜歡的猜測:這是一個提升特權的攻擊

把這些綜合到一起,我並不難預測,可能是我們在 2018 年會使用的這些存在提升特權的 bug 的發行版,或者類似的系統推動瞭如此緊急的進展,並且在補丁集的抄送串列中出現如此多的感興趣者的名字。

最後的一個趣聞,雖然我在閱讀補丁集的時候沒有找到我要的東西,但是,在一些代碼中標記,paravirtual 或者 HVM Xen 是不受此影響的。

吃瓜群眾表示 2018 將很有趣

這些猜想是完全有可能的,它離實現很近,但是可以肯定的是,當這些事情被公開後,那將是一個非常令人激動的幾個星期。


via: http://pythonsweetness.tumblr.com/post/169166980422/the-mysterious-case-of-the-linux-page-table

作者:python sweetness[15] 譯者:qhwdw 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出

LCTT 譯者

qhwdw ? ? ? ?
共計翻譯:44 篇
貢獻時間:74 天


推薦文章

< 左右滑動查看相關文章 >

點擊圖片、輸入文章 ID 或識別二維碼直達

赞(0)

分享創造快樂