谷歌正尋求提高 C++ 內(nèi)存安全
谷歌 Chrome 安全團(tuán)隊(duì)稱其一直在致力于改善 Chrome 瀏覽器的內(nèi)存安全;近期,該團(tuán)隊(duì)正在研究使用 heap scanning 技術(shù)來(lái)提高 C++ 的內(nèi)存安全。
雖然從內(nèi)存安全方面出發(fā),Rust 當(dāng)下可能更受大眾喜愛(ài)。但 Chrome 安全團(tuán)隊(duì)認(rèn)為,盡管人們對(duì)比 C++ 具有更強(qiáng)內(nèi)存安全保證的其他語(yǔ)言有興趣,但在可預(yù)見(jiàn)的未來(lái),像 Chromium 這樣的大型代碼庫(kù)將使用 C++。鑒于此,Chrome 工程師已經(jīng)找到了使 C++ 更安全的方法,以減少緩沖區(qū)溢出和 use-after free (UAF) 等與內(nèi)存相關(guān)的安全漏洞。數(shù)據(jù)表明,這些漏洞占所有軟件安全漏洞的 70%。
auto* foo = new Foo();
delete foo;
// The memory location pointed to by foo is not representing
// a Foo object anymore, as the object has been deleted (freed).
foo->Process();
如上示例,當(dāng)應(yīng)用程序使用的內(nèi)存被返回到底層系統(tǒng),但指針指向一個(gè)過(guò)期的對(duì)象時(shí),就會(huì)出現(xiàn)一個(gè)被稱為懸空指針(dangling pointers)的情況,通過(guò)它進(jìn)行的任何訪問(wèn)都會(huì)導(dǎo)致 UAF 訪問(wèn)。在最好的情況下,此類錯(cuò)誤會(huì)導(dǎo)致 well-defined 的崩潰;在最壞的情況下,它們會(huì)造成可以被惡意行為者利用的破壞。
在較大的代碼庫(kù)中,UAF 通常很難被發(fā)現(xiàn),因?yàn)閷?duì)象的所有權(quán)是在不同組件之間轉(zhuǎn)移的。這個(gè)問(wèn)題非常普遍,以至于到目前為止,工業(yè)界和學(xué)術(shù)界都在頻繁地針對(duì)其提出緩解策略。而 Chrome 中 C++ 的使用也沒(méi)有什么不同,大多數(shù)高嚴(yán)重性安全漏洞都是 UAF 問(wèn)題。近期發(fā)布的 Chrome 102 中,就修復(fù)了一個(gè)關(guān)鍵的 UAF 問(wèn)題,且八個(gè)高危漏洞中有?六個(gè)是 UAF。
為了解決這一問(wèn)題,Chrome 方面已經(jīng)使用了各種技術(shù)手段;包括 C++ 智能指針(如 MiraclePtr?)、編譯器中的靜態(tài)分析、動(dòng)態(tài)工具(如 C++ sanitizers )、代碼模糊器,以及一個(gè)名為 Oilpan 的 C++ 垃圾回收器。Oilpan、MiraclePtr 和基于智能指針的解決方案需要大量采用應(yīng)用程序代碼。
此外,谷歌還探索了另一種方法:內(nèi)存隔離(memory quarantine)?;舅悸肥菍?explicitly freed memory 放入隔離區(qū),并且僅在達(dá)到特定安全條件時(shí)才使其可用。Chrome 安全團(tuán)隊(duì)在博文中總結(jié)了在 Chrome 中實(shí)驗(yàn)隔離和 heap scanning 的歷程。
工作原理在于,用隔離和 heap scanning 保證 temporal safety 的主要思想是避免重用內(nèi)存,直到證明沒(méi)有更多的(懸空的)指針指向它。為了避免改變 C++ 用戶代碼或其語(yǔ)義,提供 new 和 delete 的內(nèi)存分配器被攔截。
在調(diào)用刪除時(shí),內(nèi)存實(shí)際上被放入隔離區(qū),無(wú)法再用于應(yīng)用程序的后續(xù)新調(diào)用?!霸谀承r(shí)候觸發(fā)了 heap scan,它掃描整個(gè)堆,就像垃圾回收器一樣,以查找對(duì)隔離內(nèi)存塊的引用。那些沒(méi)有從常規(guī)應(yīng)用內(nèi)存中獲得引用的塊被轉(zhuǎn)移回分配器,在那里它們可以被重新用于后續(xù)的分配。”
根據(jù)介紹,谷歌的 heap scanning 由一套被命名為 StarScan(簡(jiǎn)稱為 *Scan)的算法組成。他們將 *Scan 應(yīng)用于渲染器進(jìn)程的非托管部分,使用 Speedometer2 評(píng)估性能影響,并嘗試了不同版本的 *Scan。
測(cè)試結(jié)果表明,*Scan 的一個(gè)基礎(chǔ)版本造成了 8% 的內(nèi)存回歸。“所有這些開(kāi)銷從何而來(lái)?不出所料,heap scanning 極其受 memory bound 影響,因?yàn)閽呙杈€程必須遍歷和檢查整個(gè)用戶內(nèi)存的引用”。在進(jìn)行了多方面優(yōu)化之后,Speedometer2 回歸從 8% 降低到了 2%。此外,有關(guān)內(nèi)存消耗的測(cè)量結(jié)果則表明,渲染進(jìn)程中的掃描使內(nèi)存消耗減少約 12%。
MTE(內(nèi)存標(biāo)簽擴(kuò)展,Memory Tagging Extension)是 ARM v8.5A 架構(gòu)上的一個(gè)新擴(kuò)展,有助于檢測(cè)軟件內(nèi)存使用中的錯(cuò)誤;這些錯(cuò)誤可以是 spatial errors(如 out-of-bounds accesses),也可以是 temporal errors(use-after-free)。谷歌方面獲得了一些支持 MTE 的 actual hardware,并在渲染器過(guò)程中重新進(jìn)行了實(shí)驗(yàn)。結(jié)果表明,雖然 MTE 和 memory zeroing 會(huì)帶來(lái)一些成本,但 Speedometer2 中的內(nèi)存回歸約為 2%。實(shí)驗(yàn)還表明,在 MTE 之上添加 *Scan 沒(méi)有可衡量的成本。
Chrome 安全團(tuán)隊(duì)最后總結(jié)稱,C++ 可以編寫出高性能應(yīng)用程序,但需要付出安全性方面的代價(jià)。Hardware memory tagging 可以修復(fù) C++ 的一些安全缺陷,同時(shí)保持高性能?!拔覀兤诖谖磥?lái)看到更廣泛地采用 Hardware memory tagging,并建議在 Hardware memory tagging 之上使用 *Scan 來(lái)修復(fù) C++ 的 temporary memory safety。使用的 MTE 硬件和 *Scan 的實(shí)現(xiàn)都是 prototypes,我們預(yù)計(jì)仍有性能優(yōu)化的空間。”
本文轉(zhuǎn)自O(shè)SCHINA
本文標(biāo)題:谷歌正尋求提高 C++ 內(nèi)存安全
本文地址:https://www.oschina.net/news/198093/google-c-memory-safety