【bsauce讀論文】Razzer:Finding Kernel Race Bugs through Fuzzing-S&P-2019


1. 摘要

目標(biāo):挖掘競爭漏洞,如CVE-2016-8655, CVE-2017-2636, CVE-2017-17712。

問題:race漏洞受到系統(tǒng)不確定行為的影響,如線程調(diào)度與同步機(jī)制。

技術(shù):靜態(tài)分析定位可能引發(fā)競爭的代碼;確定性的線程交錯技術(shù),控制線程調(diào)度,提供準(zhǔn)確的并行執(zhí)行信息,降低不確定性。

對比:Syzkaller[42],SKI[16]。

結(jié)果:發(fā)現(xiàn)30個競爭漏洞,16個已確認(rèn)。

2. 問題與設(shè)計需求

(1)數(shù)據(jù)競爭定義

????若兩條指令滿足以下條件則為數(shù)據(jù)競爭:

????????????a.訪問的內(nèi)存地址相同

????????????b.至少其中一條指令是對內(nèi)存的寫

????????????c.兩條指令可以并發(fā)執(zhí)行

(2)標(biāo)記

標(biāo)記

(3)競爭案例—CVE-2017-2636

? ??????兩個線程分別調(diào)用ioctl(fd,TCFLSH)和write(fd,…),對變量n_hdlc->tbuf的并發(fā)讀寫導(dǎo)致競爭(n_hdlc->tbuf = NULL;與tbuf = n_hdlc->tbuf;),該內(nèi)存地址在free_list中保存了兩次,最后ioctl(fd,TCXONC)將導(dǎo)致double free。

Fig1-競爭案例—CVE-2017-2636?

(4)設(shè)計要求

R1——找到執(zhí)行RacePair_cand的輸入程序。即找到一個多線程的用戶態(tài)程序,每個線程能夠在內(nèi)核態(tài)分別執(zhí)行到RacePair_cand的指令。需求1把問題做了簡化,并不去考慮并行執(zhí)行的問題,就不用考慮線程調(diào)度對分析的影響。

R2——根據(jù)R1輸入程序,找到并發(fā)執(zhí)行RacePair_cand的線程執(zhí)行序列。需求2主要是去尋找一個交錯執(zhí)行的線程調(diào)度方案,使得RacePair_cand的指令能并行執(zhí)行。

3.?設(shè)計

? ? 整體流程如圖:

Fig3-Razzer總體架構(gòu)

3.1靜態(tài)分析—識別RacePair_cand

方法:指向分析(尋找內(nèi)核中對同一個結(jié)構(gòu)體的內(nèi)存訪問),但限制是準(zhǔn)確率與性能,需要精確的CF/DF信息(運(yùn)行時更準(zhǔn)確)和并發(fā)信息(受到調(diào)度和同步原語的影響)。指向分析的時間開銷是O(n^3)。

Razzer改進(jìn)

(1)準(zhǔn)確性

????????采用指向分析得到近似的RacePair_cand(上下文敏感、流敏感、區(qū)域敏感),后續(xù)通過動態(tài)分析來確認(rèn)。去除不會引起競爭的指令,例如訪問結(jié)構(gòu)中不同變量。

(2)性能

????????分部分分析,減小分析的代碼量。作者按目錄結(jié)構(gòu)劃分模塊,如kernel, mm, fs, drivers,但有些模塊如fs和net/core會被每個模塊調(diào)用。

缺點(diǎn):未分析同步原語如read_lock(), br_read_lock(), spin_lock_irqsave(), up(),該分析可以排除不會引發(fā)競爭的內(nèi)存對。

3.2 線程調(diào)度-hypervisor

方法:待Fuzz的內(nèi)核運(yùn)行在虛擬化的環(huán)境中,為了控制虛擬CPU的調(diào)度,作者修改了虛擬環(huán)境的Hypervisor,增加了三個功能。

(1)為每個虛擬CPU設(shè)置斷點(diǎn)

超級調(diào)用接口:hcall_set_bp(vCPU_TD, guest_addr)。由虛擬機(jī)guest kernel調(diào)用,監(jiān)管者收到后在guest_addr地址下硬件斷點(diǎn)。

兩點(diǎn)要求:

????????a.準(zhǔn)確設(shè)置每個vCPU的斷點(diǎn):斷點(diǎn)地址存入virtualized debug register,每個vCPU有一個VDR,就能保證只有相關(guān)vCPU執(zhí)行時才會觸發(fā)斷點(diǎn);設(shè)置Intel VT-x中Virtual Machine Control Structure (VMCS)的中斷表的相應(yīng)位(硬件斷點(diǎn)中斷),就能保證VMEXIT事件首先交給監(jiān)管器而非guest kernel。

????????b.確定斷點(diǎn)是否被指定內(nèi)核線程觸發(fā):有可能是其他無關(guān)線程觸發(fā),利用virtual machine introspection(VMI)獲取內(nèi)核線程上下文,找到線程號,也即通過thread_info -> task_struct -> 內(nèi)核線程號,確定是否被指定內(nèi)核線程觸發(fā)。

(2)控制線程執(zhí)行順序

????????Hcall_set_order(vCPU_ID),恢復(fù)指定線程執(zhí)行,不同的執(zhí)行順序決定是否觸發(fā)錯誤。

(3)檢測競爭結(jié)果

檢查競爭指令訪問地址是否相同,相同則為RacePair_true。

3.3 多線程fuzz

(1)單線程fuzzing

目的:生成單線程程序,執(zhí)行RacePair_cand。

generator:生成單線程用戶程序P_st—隨機(jī)syscall序列。

????????????????兩種策略:一是generation,使用syzkaller[42]定義的syscall語法(含參數(shù)值范圍),生成隨機(jī)調(diào)用序列,傳遞調(diào)用參數(shù);二是mutation,對已有的P_st進(jìn)行drop/insert/change。

executor:執(zhí)行P_st。

????????????a.用KCov[3]收集執(zhí)行覆蓋路徑,看是否有2個syscall執(zhí)行RacePair_cand指令;

????????????b.記錄這2個syscall+RacePair_cand在syscall中地址+P_st,發(fā)送給多線程fuzzing。

? ? ? ? ? ? 反饋:若某個P_st產(chǎn)生新的路徑覆蓋,則作為反饋加入到變異種子隊列。

(2)多線程fuzzing

目的:生成多線程程序,觸發(fā)競爭。

generator:P_st→P_mt,轉(zhuǎn)化為一個多線程版本P_mt。在轉(zhuǎn)換過程中還會進(jìn)行一些插樁,與Hypervisor協(xié)作控制程序的調(diào)度。輸入P_st,i(syscall下標(biāo)),j,RP_i,RP_j(競爭指令地址)。

executor:運(yùn)行P_mt,檢測RacePair_cand是否觸發(fā)競爭。

????????????判斷條件:a.捕捉到2個斷點(diǎn)RacePair_cand;b. RacePair_cand指令訪問地址相同。

????????????razzer競爭檢查:使用lockdep[29],KASAN[2],或手動插入assertion。

????????????反饋:導(dǎo)致競爭的P_mt用于進(jìn)一步變異,以觸發(fā)崩潰。

4.實現(xiàn)

4.1 靜態(tài)分析

????????基于LLVM+SVF[39]。

????????改進(jìn)SVF—指向分析:處理內(nèi)核內(nèi)存分配/釋放;處理堆/全局結(jié)構(gòu)中的非指針變量。

????????輸出:RacePair_cand(含源文件名+行號),編譯利用GCC的調(diào)試信息將之轉(zhuǎn)化為二進(jìn)制地址。

4.2 hypervisor

????????基于QEMU+KVM(kernel-based Virtual Machine)硬件加速;

????????Capstone[1]反匯編來檢查RacePair_cand;

????????fuzzer基于Syzkaller[42]。

4.3 代碼量

????????SVF靜態(tài)分析—638 LoC C++;

????????QEMU實現(xiàn)hypervisor 652 LoC c;

????????Syzkaller實現(xiàn)fuzzer 6403 LoC Go和286 LoC。

5.評價

(1)發(fā)現(xiàn)的競爭漏洞,競爭漏洞列表見Fig6。

????????能發(fā)現(xiàn)很老的洞,2007,見Fig8。

????????Report對于漏洞修復(fù)幫助很大

(2)靜態(tài)分析有效性

????????分部分分析效率很高見Fig9,整體分析耗時7天。

????????RacePair_cand有效性,有效引導(dǎo)到低于0.1%的可疑競爭點(diǎn)。

(3)hypervisor性能開銷

????????hypercall開銷很小,見Fig12。

(4)與syzkaller/SKI工具進(jìn)行比較

????????找單線程輸入程序:執(zhí)行速度慢于syzkaller,但找有害競爭快于syzkaller。

????????找多線程交錯程序:由于SKI不開源,所以根據(jù)SKI隨機(jī)線程交錯特性實現(xiàn)SKI_Emu—修改Razzer的多線程fuzzing部分(不使用hypercall),效率明顯高于SKI。

6. 未來工作

(1)優(yōu)化靜態(tài)分析

????????本文假設(shè)不同內(nèi)核模塊之間很少有競爭,分部分分析導(dǎo)致錯過很多RacePair_cand;提高靜態(tài)分析的準(zhǔn)確性,以識別不會競爭的指令對,可分析同步原語[14,41](如read_lock(), br_read_lock(), spin_lock_irqsave(), up(),該分析可以排除不會引發(fā)競爭的內(nèi)存對)。

(2)擴(kuò)展性

????????移植到別的OS,如Windows/MacOSX/FreeBSD。

????????擴(kuò)展到用戶程序分析,用戶程序不需要其他變異策略,因為用戶程序競爭和內(nèi)核不一樣,只要發(fā)生競爭都算作漏洞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容