<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          LWN: Spectre 漏洞利用了BPF!

          共 3577字,需瀏覽 8分鐘

           ·

          2021-07-17 06:03

          關(guān)注了就能看到更多這么棒的文章哦~

          Spectre revisits BPF

          By Jonathan Corbet
          June 24, 2021
          DeepL assisted translation
          https://lwn.net/Articles/860597/

          自 Spectre 硬件漏洞被披露以來(lái),已經(jīng)過(guò)去三年了,但 Spectre 仍在不斷給我們新的意外。在硬件行為完全可以預(yù)測(cè)的情況下要想寫(xiě)出正確且安全的代碼已經(jīng)很困難了,而如果處理器會(huì)隨機(jī)做出一些無(wú)法預(yù)測(cè)到的行為的時(shí)候,情況就變得更加困難了。為了說(shuō)明這里會(huì)面臨的挑戰(zhàn),我們只需要看看這個(gè)公告(https://lwn.net/ml/oss-security/CAHMfzJkhZ01FG62sfMdXayK_NwD3g=5NcpGmg+-PVZLBpjJ9Fw@mail.gmail.com/)中所介紹的 BPF 漏洞就好,這個(gè)漏洞本身已在 5.13-rc7 版本中得到了 fix。

          針對(duì) Spectre 漏洞的攻擊一般是先要讓處理器在 speculative mode 下執(zhí)行一系列在現(xiàn)實(shí)代碼中不會(huì)發(fā)生的操作。典型的例子就是訪問(wèn)超出數(shù)組范圍之外的位置(out-of-range array reference),盡管代碼本身已經(jīng)正確地進(jìn)行了邊界檢查。當(dāng)處理器發(fā)現(xiàn)它錯(cuò)誤地預(yù)測(cè)了邊界檢查的結(jié)果的時(shí)候,就會(huì)把之前進(jìn)行的錯(cuò)誤的訪問(wèn)撤銷(xiāo),但是這個(gè) speculative access(預(yù)測(cè)性訪問(wèn))會(huì)在 cache 中留下痕跡,這樣就可以被用來(lái)探測(cè)有價(jià)值的數(shù)據(jù)了。

          在抵御這類(lèi)預(yù)測(cè)執(zhí)行的攻擊方面,BPF 虛擬機(jī)一直是一個(gè)特別值得關(guān)注的領(lǐng)域。大多數(shù)這類(lèi)攻擊都依賴(lài)于找到內(nèi)核代碼的某個(gè)片段,當(dāng) CPU 進(jìn)行預(yù)測(cè)執(zhí)行時(shí),利用這段代碼來(lái)做一些破壞性的工作。內(nèi)核開(kāi)發(fā)者已經(jīng)做了不少努力來(lái)消除這樣的代碼片段。但是,BPF 的存在就是為了能夠加載來(lái)自用戶(hù)空間的、可以運(yùn)行在內(nèi)核上下文中的代碼,這就使得攻擊者能夠制作他們自己的代碼,而不用再?gòu)?kernel 代碼中尋找攻擊目標(biāo)了。

          為了挫敗這些攻擊者,BPF 社區(qū)已經(jīng)做了很多工作。例如將數(shù)組索引(array index)與一個(gè) bitmask 進(jìn)行 AND 操作,這樣一來(lái)訪問(wèn)數(shù)組的時(shí)候就不會(huì)越過(guò)數(shù)組邊界了,即使 CPU 是在 speculative 模式并且這些索引是亂七八糟的值也不怕了。但人們還是很難列出處理器在各種情況下的處理方式,難免會(huì)遺漏一些場(chǎng)景。

          The vulnerability

          下面的代碼就是一個(gè)例子,來(lái)自 Daniel Borkmann 對(duì)這個(gè)漏洞進(jìn)行 fix 時(shí)提交的說(shuō)明:

          // r0 = pointer to a map array entry
          // r6 = pointer to readable stack slot
          // r9 = scalar controlled by attacker
          1: r0 = *(u64 *)(r0) // cache miss
          2: if r0 != 0x0 goto line 4
          3: r6 = r9
          4: if r0 != 0x1 goto line 6
          5: r9 = *(u8 *)(r6)
          6: // leak r9

          順便說(shuō)一下,這個(gè) patch 的 changelog 非常值得一讀,在記錄漏洞本身以及相關(guān) fix 方面是一個(gè)非常棒的例子。

          在正常(non-speculative)執(zhí)行時(shí),上述代碼有一個(gè)潛在問(wèn)題。寄存器 r9 包含的是攻擊者提供的值,這個(gè)數(shù)值在第 3 行被賦值給 r6,然后在第 5 行被用作指針了。這個(gè)值可能是指向內(nèi)核地址空間的任何地方的,這正是 BPF verifier 想要阻止的那種無(wú)拘無(wú)束的訪問(wèn)操作,所以人們可能會(huì)以為這段代碼肯定不會(huì)被 kernel 接受并執(zhí)行。

          但是,BPF verifier 的工作機(jī)制是遍歷執(zhí)行 BPF program 的所有可能代碼分支來(lái)判斷是否接受。它的遍歷中,并不會(huì)既執(zhí)行第 3 行又執(zhí)行第 5 行。因?yàn)楣粽咛峁┑闹羔樫x值操作只有在 r0 內(nèi)容是 0 時(shí)才會(huì)發(fā)生,但這個(gè)值會(huì)導(dǎo)致第 5 行不會(huì)得到執(zhí)行。BFP Verifier 因此得出結(jié)論,認(rèn)為沒(méi)有任何執(zhí)行流程會(huì)導(dǎo)致把用戶(hù)提供數(shù)據(jù)當(dāng)作指針進(jìn)行了訪問(wèn),于是它就正常加載并執(zhí)行了這個(gè) BPF Program。

          但是這個(gè)驗(yàn)證分析完全是按照正常執(zhí)行的情況來(lái)進(jìn)行的,在 CPU 根據(jù) speculative 執(zhí)行的過(guò)程中則并不遵照這種規(guī)則。

          上面這段代碼中的第 1 行中引用的這塊內(nèi)存,攻擊者會(huì)想盡辦法來(lái)讓這段內(nèi)存不存在于 CPU cache 中,這樣第一行的訪問(wèn)就會(huì)觸發(fā)一次 cache miss。而處理器并不會(huì)等待從內(nèi)存中取到的數(shù)值,而是根據(jù)預(yù)測(cè)來(lái)進(jìn)行執(zhí)行后續(xù)與 r0 有關(guān)的代碼。而實(shí)際上這些預(yù)測(cè)的結(jié)果有可能會(huì)導(dǎo)致兩處 if 條件(在第 2 行或第 4 行)都被判斷為 false,于是就不會(huì)進(jìn)行跳轉(zhuǎn)。

          這種情況怎么可能會(huì)出現(xiàn)呢?原因是,branch prediction(分支預(yù)測(cè))并不是通過(guò)猜測(cè) r0 的值來(lái)進(jìn)行判斷來(lái)實(shí)現(xiàn)的。其實(shí)它是基于某個(gè)特定代碼分支最近幾次執(zhí)行的歷史來(lái)判斷的。這個(gè)歷史信息
          存儲(chǔ)在 CPU 的 "pattern history table"(PHT)中。但是,CPU 不可能跟蹤記錄某個(gè)大型程序中的每一條 branch 指令,所以 PHT 就采用了 hash table 的形式。攻擊者會(huì)尋找一些代碼,使得它的 branch 會(huì)被放在精心設(shè)計(jì)的 BPF program 中的 branch 相同的 PHT 條目位置內(nèi),然后使用該代碼來(lái)調(diào)教 branch predicator,從而誘使其最終按攻擊者的期望來(lái)進(jìn)行預(yù)測(cè)執(zhí)行。

          一旦攻擊者加載了這段代碼,清除了 cache,并愚弄了 branch predicator 做出了啥事,那么攻擊者的目的就達(dá)到了,CPU 會(huì)根據(jù)預(yù)測(cè)來(lái)訪問(wèn)引用攻擊者提供的地址。后續(xù)只需要用一些常規(guī)方式來(lái)把結(jié)果暴露出來(lái)就可以完成攻擊了。這個(gè)過(guò)程還是挺麻煩的,但是計(jì)算機(jī)天生就適合做這種重復(fù)執(zhí)行的操作。

          值得注意的是,這種攻擊方式并不僅存在于假想之中。根據(jù)上面的公告,當(dāng)這個(gè)問(wèn)題被報(bào)出來(lái)的時(shí)候, [email protected] 列表上就收到了很多個(gè) proofs-of-concept 的攻擊方案。其中一些方案都不需要對(duì) branch predicator 進(jìn)行調(diào)教的步驟。這些攻擊可以讀到內(nèi)核地址空間中的任意內(nèi)存的內(nèi)容,在所有物理內(nèi)存都屬于內(nèi)核地址空間的系統(tǒng)上,相當(dāng)于任何數(shù)據(jù)都可以被竊取到了。由于非特權(quán)用戶(hù)也可以加載某些類(lèi)型的 BPF program,所以攻擊者都不需要 root 權(quán)限。換句話(huà)說(shuō),這是一個(gè)嚴(yán)重的漏洞(serious vulnerability)。

          Closing the hole

          針對(duì)這種問(wèn)題的 fix 是比較簡(jiǎn)單易懂的。BPF Verifier 不要再去跳過(guò)那些它明知道不可能執(zhí)行的代碼分支就好,而是根據(jù) speculative 的方式來(lái)模擬執(zhí)行這些路徑。這樣一來(lái),在看到 r0 為零的代碼分支時(shí),之前有問(wèn)題的 verifier 會(huì)簡(jiǎn)單地得出結(jié)論認(rèn)為第 4 行的判斷結(jié)果一定是 true,而不再考慮其他可能。在 fix 后,verifier 仍然會(huì)走到 false 的分支里去(包括第 5 行),從而得出結(jié)論這里正在使用一個(gè)未知指針,從而禁止加載這個(gè) BPF program。

          這個(gè)改動(dòng)有可能會(huì)導(dǎo)致之前能正常運(yùn)行的正確代碼也無(wú)法加載了,盡管很難想到有哪些正常代碼會(huì)包含這類(lèi)的代碼 pattern。當(dāng)然,這將會(huì)導(dǎo)致 verifier 進(jìn)行檢查時(shí)所花費(fèi)的時(shí)間更長(zhǎng),因?yàn)樗枰獧z查在正常程序執(zhí)行中不可能出現(xiàn)的代碼路徑,但我們沒(méi)有辦法,誰(shuí)讓我們面對(duì)的是這些會(huì)進(jìn)行 speculative 執(zhí)行的 CPU 呢。

          這個(gè) fix 已經(jīng)被合入了 mainline,可以在 5.13-rc7 版本中找到。此后,它又被合入了 5.12.13 和 5.10.46 這兩個(gè)穩(wěn)定版的 update 中,但目前(還)沒(méi)有進(jìn)入那些更早期的 stable kernel。有了這個(gè) fix 的內(nèi)核就可以防止另一個(gè) Spectre 漏洞被利用了,但如果認(rèn)為這是最后一個(gè),那就太天真了。

          全文完
          LWN 文章遵循 CC BY-SA 4.0 許可協(xié)議。

          歡迎分享、轉(zhuǎn)載及基于現(xiàn)有協(xié)議再創(chuàng)作~

          長(zhǎng)按下面二維碼關(guān)注,關(guān)注 LWN 深度文章以及開(kāi)源社區(qū)的各種新近言論~



          瀏覽 78
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  性爱一级片| 乱伦亚洲色國片 | 青青草一区二区三区 | 做爱网站在线观看 | 国产视频一二三 |