Chrome Native Client 原理
Native Client:A Sandbox for Portable, Untrusted x86 Native Code
系統(tǒng)架構(gòu)
??????一個(gè)NaCl應(yīng)用程序由許多可信和不可信NaCl模塊組成,每個(gè)模塊都在一個(gè)進(jìn)程中單獨(dú)運(yùn)行。假想一個(gè)基于NaCL實(shí)現(xiàn)的,用于管理和分享圖片的應(yīng)用,它由兩個(gè)組件構(gòu)成,一個(gè)用javascript實(shí)現(xiàn)的用戶界面接口,運(yùn)行在web瀏覽器中,另一個(gè)是圖片處理庫(kù),作為一個(gè)Native Client模塊實(shí)現(xiàn)。在這個(gè)場(chǎng)景,兩者都是不可信的。瀏覽器組件通過(guò)瀏覽器執(zhí)行環(huán)境進(jìn)行限制,而圖片處理庫(kù)通過(guò)Native Client容器進(jìn)行限制。在運(yùn)行這個(gè)圖片應(yīng)用前,用戶必須將Native Client作為瀏覽器插件進(jìn)行安裝,我們將它視為一個(gè)可信的NaCl模塊。
??????當(dāng)用戶訪問(wèn)我們這個(gè)圖片應(yīng)用的web站點(diǎn)時(shí),瀏覽器會(huì)加載并執(zhí)行應(yīng)用程序的javascript組件部分,后者會(huì)通過(guò)Native Client插件去加載圖片處理庫(kù)到Native Client容器中來(lái)。這個(gè)加載過(guò)程不會(huì)跳出提示窗口的,Native Client負(fù)責(zé)對(duì)本地應(yīng)用模塊的行為進(jìn)行限制。
??????每個(gè)組件都運(yùn)行在它私有的地址空間內(nèi)。組件間通信是通過(guò)NaCl的可靠數(shù)據(jù)包服務(wù)---模塊間通信(IMC)來(lái)進(jìn)行的。NaCl為瀏覽器和NaCl模塊之間的通信提供了兩種方式:簡(jiǎn)單遠(yuǎn)程過(guò)程調(diào)用(SRPC),Netscape插件應(yīng)用程序接口(NPAPI),這兩者都基于IMC實(shí)現(xiàn)。為了避免訪高頻率的通信帶來(lái)的消息負(fù)擔(dān),IMC還提供了共享內(nèi)存段和共享同步對(duì)象。
????? NaCl模塊還可以訪問(wèn)”服務(wù)運(yùn)行時(shí)”,它提供了內(nèi)存管理操作,創(chuàng)建線程和其他系統(tǒng)服務(wù)。這個(gè)接口和操作系統(tǒng)的系統(tǒng)調(diào)用接口類似。應(yīng)用程序中可以包含多個(gè)Native Client模塊,并且可信和不可信模塊都可以使用IMC。例如,上面說(shuō)的圖片應(yīng)用的用戶可以選擇安裝一個(gè)可信的NaCl服務(wù),用于圖片的本地存儲(chǔ)。由于它能訪問(wèn)本地硬盤,因此這個(gè)存儲(chǔ)服務(wù)必須作為一個(gè)本地的瀏覽器插件安裝,而不能作為一個(gè)Native Client模塊實(shí)現(xiàn)。在應(yīng)用程序初始化時(shí),用戶接口會(huì)檢查這個(gè)存儲(chǔ)服務(wù)是否可用,若可用,則會(huì)與它建立一個(gè)IMC通信通道,并把這個(gè)通信通道的描述符傳遞給圖片處理庫(kù),從而是兩者可以通過(guò)基于IMC的服務(wù)(SRPC,共享內(nèi)存等)進(jìn)行直接通信。這種情況下,NaCl模塊一般會(huì)靜態(tài)鏈接到一個(gè)負(fù)責(zé)提供過(guò)程接口來(lái)訪問(wèn)存儲(chǔ)服務(wù)的庫(kù),這個(gè)庫(kù)對(duì)底層的IMC層面的通信細(xì)節(jié)實(shí)現(xiàn)進(jìn)行封裝,從而不用理會(huì)底層到底使用的是SRPC還是共享內(nèi)存。存儲(chǔ)服務(wù)組件假定圖片處理庫(kù)是不可信的,并確保只執(zhí)行符合接口契約的服務(wù)。
??????類似上面存儲(chǔ)服務(wù)這樣的組件一般在NaCl內(nèi)核以外實(shí)現(xiàn),這類似操作系統(tǒng)的微內(nèi)核模型,簡(jiǎn)單,穩(wěn)定,松耦合。
??????下面來(lái)詳細(xì)介紹NaCl系統(tǒng)的各個(gè)組成部分的設(shè)計(jì)。
內(nèi)外兩層沙箱
??????Native Client基于x86進(jìn)程內(nèi)“內(nèi)層沙箱“構(gòu)建而成。而為了進(jìn)一步防御攻擊,還構(gòu)建了一個(gè)”外層沙箱“用于進(jìn)程邊界的隔離。
??????內(nèi)層沙箱使用代碼靜態(tài)分析技術(shù)來(lái)在不可信的x86代碼中檢查安全隱患。以前這樣的分析受到了很多技術(shù)的挑戰(zhàn),比如說(shuō)可自我修改的代碼,重疊指令。為了解決這樣的問(wèn)題,在Native Client中為代碼制定了一系列契約和結(jié)構(gòu)規(guī)則,從而確保本地代碼模塊能可靠地進(jìn)行分解,然后通過(guò)代碼驗(yàn)證器來(lái)確保可執(zhí)行文件只包含合法指令集中的指令。
??????內(nèi)層沙箱還利用了x86內(nèi)存分段機(jī)制來(lái)限制數(shù)據(jù)和指令的內(nèi)存引用。
內(nèi)層沙箱用于在一個(gè)本地進(jìn)程中創(chuàng)建一個(gè)安全的子域。在這個(gè)子域中我們可以將一個(gè)可信的運(yùn)行時(shí)服務(wù)(Service Runtime)子系統(tǒng)和不可信模塊放置在同一個(gè)進(jìn)程中。通過(guò)一個(gè)安全的跳躍/計(jì)分板機(jī)制來(lái)允許可信代碼和不可信代碼之間的控制轉(zhuǎn)移。
內(nèi)層沙箱不僅將系統(tǒng)與本地模塊進(jìn)行分離,而且還使得本地模塊與操作系統(tǒng)進(jìn)行了分離。
外層沙箱是第二道防御機(jī)制。它會(huì)對(duì)運(yùn)行NaCl模塊的進(jìn)程的所有系統(tǒng)調(diào)用,通過(guò)與一個(gè)允許的系統(tǒng)調(diào)用白名單進(jìn)行比對(duì)來(lái)拒絕或通過(guò)此調(diào)用。目前白名單上允許的系統(tǒng)調(diào)用有46個(gè)。
運(yùn)行時(shí)機(jī)制
??????IMC允許可信和不可信模塊之間越過(guò)進(jìn)程邊界發(fā)送/接收包含無(wú)類型字節(jié)數(shù)組的數(shù)據(jù)包,還可以包含用于文件共享,共享內(nèi)存對(duì)象,通信通道的”NaCl資源描述符“。第一種方式是SRPC,它用于定義和使用子過(guò)程來(lái)跨模塊邊界訪問(wèn),包括從瀏覽器中的javascript調(diào)用NaCl代碼。第二種是NPAPI,它提供了與瀏覽器狀態(tài)交互的接口,包括打開(kāi)URL,訪問(wèn)DOM。這兩種機(jī)制都可以用來(lái)與瀏覽器進(jìn)行交互,包含頁(yè)面內(nèi)容修改,處理鼠標(biāo)和鍵盤事件,獲取其他站點(diǎn)內(nèi)容,因?yàn)檫@些都可以通過(guò)javascript訪問(wèn)。
??????如上所說(shuō),運(yùn)行時(shí)服務(wù)負(fù)責(zé)為NaCl模塊之間,以及和瀏覽器之間交互提供容器。它一般會(huì)提供應(yīng)用程序編程環(huán)境相適應(yīng)的一系列系統(tǒng)服務(wù)。為了支持malloc/free接口或其他內(nèi)存分配抽象機(jī)制,它提供了sbrk()和mmap()系統(tǒng)調(diào)用。它提供了POSIX線程接口的一個(gè)子集,用于線程的創(chuàng)建和銷毀,條件變量,互斥量,信號(hào)量,線程本地存儲(chǔ)。它還提供了常用的POSIX文件I/O接口,用于通信通道以及基于web的只讀內(nèi)容的操作。為了防止惡意的網(wǎng)絡(luò)訪問(wèn),connect()和accept()這樣的系統(tǒng)調(diào)用不可使用。
攻擊層面
??????從內(nèi)而外,有以下幾個(gè)層面會(huì)受到攻擊者關(guān)注:
????? 1)內(nèi)層沙箱:二進(jìn)制驗(yàn)證
????? 2)外層沙箱:OS系統(tǒng)調(diào)用截取
????? 3)服務(wù)運(yùn)行時(shí)二進(jìn)制模塊加載器
????? 4)服務(wù)運(yùn)行時(shí)跳轉(zhuǎn)接口
????? 5)IMC通信接口
????? 6)NPAPI接口
??????除了內(nèi)外層沙箱,系統(tǒng)還包含了CPU和NaCl模塊白名單機(jī)制。
?下面來(lái)看各個(gè)組件詳細(xì)的實(shí)現(xiàn)細(xì)節(jié)
內(nèi)層沙箱
??????這層僅限于機(jī)器代碼中明顯的控制流(即調(diào)用和跳轉(zhuǎn))。其他類型的控制流(如異常)在NaCl運(yùn)行時(shí)服務(wù)中處理。
??????內(nèi)層沙箱定義了一系列用于可靠分解的規(guī)則,一個(gè)用于監(jiān)視這些規(guī)則的編譯工具鏈,以及一個(gè)確保代碼符合規(guī)則的靜態(tài)代碼分析器,通過(guò)這三者來(lái)實(shí)現(xiàn)代碼的可信檢查。
NaCl模塊二進(jìn)制代碼規(guī)則:
C1?Once??loaded??into??the??memory,??the??binary??is??not??writable,?
enforced?by?OS-level?protection?mechanisms?during?execution.?
C2?The??binary??is??statically??linked??at??a??start??address??of??zero,with?the?first?byte?of?text?at?64K.??
C3?All??indirect?control?transfers?use??a?nacljmp??pseudo-??instruction?(defined?below).?
C4?The??binary??is??padded??up??to??the??nearest??page??with??at??
one?hlt?instruction?(0xf4).???
C5?The?binary?contains?no?instructions?or?pseudo-instructions??overlapping?a?32-byte?boundary.???
C6?All??valid?instruction?addresses?are??reachable?by??a??fall-??through?disassembly?that?starts?at?the?load?(base)?address.?????
C7?All?direct?control?transfers?target?valid?instructions.????????????????????????????????????????????????????????????????????????????
???????使用80386段來(lái)限制在虛擬32位地址空間中的連續(xù)子段中的數(shù)據(jù)引用。同時(shí)禁止一些操作碼的使用,比如syscall和int(不可信代碼就無(wú)法直接調(diào)用系統(tǒng)調(diào)用),所有修改x86段狀態(tài)的指令(如lds等),ret。允許hlt指令,但它會(huì)導(dǎo)致模塊立即終結(jié)。處于安全考慮,還禁止所有其他的特權(quán)0級(jí)的指令,因?yàn)樵谝粋€(gè)正確的用戶態(tài)指令流中不該使用。(其他的細(xì)節(jié)不翻譯了,太晦澀了)
???????我們發(fā)現(xiàn)使用的驗(yàn)證器能以30MB/s的速度對(duì)代碼進(jìn)行檢查,這與下載數(shù)據(jù)相比非常小,因此并不會(huì)造成性能上的問(wèn)題。
外層沙箱
??????若內(nèi)存沙箱被攻破,不可信代碼就可以對(duì)運(yùn)行時(shí)服務(wù)進(jìn)行訪問(wèn),但此時(shí)外層沙箱可以對(duì)進(jìn)程邊界的系統(tǒng)調(diào)用進(jìn)行控制來(lái)阻止大部分危險(xiǎn)行為。Linux上的實(shí)現(xiàn)使用了ptrace接口,在windows上將會(huì)采用訪問(wèn)控制列表(目前只有Linux上的實(shí)現(xiàn),Mac和Windows還在開(kāi)發(fā))。
????? Linux上的實(shí)現(xiàn)將NaCl容器作為一個(gè)子進(jìn)程啟動(dòng),然后使用ptrace對(duì)進(jìn)程發(fā)出的所有系統(tǒng)調(diào)用進(jìn)行檢查。外層沙箱維護(hù)有一個(gè)允許的系統(tǒng)調(diào)用白名單,試圖執(zhí)行任何白名單以外的系統(tǒng)調(diào)用都會(huì)導(dǎo)致NaCl模塊立即結(jié)束。
??????但目前使用ptrace的這個(gè)實(shí)現(xiàn)增加了每個(gè)系統(tǒng)調(diào)用的負(fù)擔(dān),因?yàn)榧词顾诎酌麊沃?#xff0c;也會(huì)進(jìn)行兩次上下文切換以及一次查表,從而確定此調(diào)用是否被允許。因此對(duì)系統(tǒng)性能會(huì)有一定影響,也就要求開(kāi)發(fā)者在使用系統(tǒng)調(diào)用方面謹(jǐn)慎,并盡量減少模塊間通信頻度,可以考慮使用共享的內(nèi)存和同步對(duì)象,這對(duì)于高訪問(wèn)頻率,高帶寬通信的應(yīng)用獲得最優(yōu)性能非常重要。
異常
??????不允許使用硬件異常(段錯(cuò)誤,浮點(diǎn)數(shù)異常)和外部中斷。為了隔離異常,每個(gè)NaCl模塊都在一個(gè)單獨(dú)進(jìn)程中運(yùn)行,無(wú)法使用異常處理來(lái)從硬件異常中恢復(fù)過(guò)來(lái),而是這個(gè)進(jìn)程會(huì)被關(guān)閉。雖然不支持硬件異常,但確實(shí)支持c++異常,但不支持Windows結(jié)構(gòu)化異常處理(WSEH).
服務(wù)運(yùn)行時(shí)
??????服務(wù)運(yùn)行時(shí)是一個(gè)本地可執(zhí)行代碼,它被一個(gè)NPAPI插件調(diào)用,這個(gè)插件也用來(lái)支持服務(wù)運(yùn)行時(shí)和瀏覽器之間的交互。它實(shí)現(xiàn)了dynamic enforcement機(jī)制,這個(gè)機(jī)制維護(hù)了內(nèi)層沙箱的完整性,并提供了一個(gè)資源抽象層,從而使得NaCl應(yīng)用程序與主機(jī)資源以及操作系統(tǒng)接口分離開(kāi)。它包含了可信的代碼和數(shù)據(jù),但與包含的NaCl模塊共享同一個(gè)進(jìn)程,且后者可以通過(guò)一個(gè)受控的接口去訪問(wèn)服務(wù)運(yùn)行時(shí)。服務(wù)運(yùn)行時(shí)通過(guò)x86的內(nèi)存分段和分頁(yè)機(jī)制相結(jié)合的方式來(lái)阻止不可信代碼的非法內(nèi)存訪問(wèn)行為。
??????當(dāng)一個(gè)NaCl模塊被加載進(jìn)來(lái),它就被置于一個(gè)服務(wù)運(yùn)行時(shí)地址空間中段分隔的256M區(qū)域內(nèi)。NaCl模塊地址空間(NaCl”用戶”空間)的前64Kb被服務(wù)運(yùn)行時(shí)保留,用于初始化。前4kb受讀寫保護(hù),用于檢查空指針。剩下的60Kb包含了實(shí)現(xiàn)“跳躍”調(diào)用門和”記分板“返回門的可信代碼段。不可信的NaCl模塊緊隨64kb后的區(qū)域加載進(jìn)來(lái)。
(筆記:在每個(gè)native plug-in process的內(nèi)部都有一段代碼叫Service Runtime,用來(lái)模擬傳統(tǒng)的system call,plug-in的system call會(huì)被重定向到這個(gè)進(jìn)程內(nèi)的Service Runtime,即從untrust code切換到trust code。在進(jìn)入Service Runtime之后,系統(tǒng)恢復(fù)我們熟悉的flat memory addressing,來(lái)訪問(wèn)操作系統(tǒng)的資源。當(dāng)然,只有少數(shù)安全的system call才會(huì)被Service Runtime處理。first level sandbox中的static analysis會(huì)保證unstruct native code不能隨意進(jìn)入Service Runtime.)
通信
????? IMC是NaCl模塊之間通信的基礎(chǔ)。它基于NaCl socket而實(shí)現(xiàn),提供了一個(gè)類似Unix domain socket的雙向,可靠,有序的數(shù)據(jù)包服務(wù)。當(dāng)一個(gè)不可信NaCl模塊被創(chuàng)建時(shí)(通過(guò)DOM和javascript來(lái)創(chuàng)建),它會(huì)接收到第一個(gè)NaCl socket。Javascript使用這個(gè)socket向NaCl模塊發(fā)送消息,也可以將其共享給其他NaCl模塊。JavaScript還可以將NaCl socket共享為NaCl?描述符,從而選擇將模塊連接到其他服務(wù)上去。NaCl描述符還可以用來(lái)創(chuàng)建共享的內(nèi)存段。
??????通過(guò)使用NaCl消息,NaCl的SRPC完全在不可信代碼中實(shí)現(xiàn)。使用SRPC可以定義JavaScript和NaCl模塊之間,或兩個(gè)NaCl模塊之間的過(guò)程接口,它支持一些基本類型(int,float,char),數(shù)組以及NaCl描述符。像XDR或Protocol Buffers這些外部數(shù)據(jù)表示層也可以很輕松地置于NaCl消息或SRPC之上
????? NPAPI的實(shí)現(xiàn)也基于IMC,并支持常用NPAPI接口的一個(gè)子集。目前支持的操作包括對(duì)瀏覽器中腳本對(duì)象的屬性和方法的讀,修改和調(diào)用,簡(jiǎn)單光柵圖形的繪制,提供createArray方法創(chuàng)建數(shù)組以及像文件描述符一樣打開(kāi)和使用URL。后續(xù)的改進(jìn)還在考慮中。
與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的Chrome Native Client 原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Dalvik記憶體
- 下一篇: LLVM(Low Level Virtu