基於兩個維度輸入空間探索的文件系統Fuzzing

Fuzzing File Systems via Two-Dimensional Input Space Exploration


Remarks

Conference: S&P 2019
Full Paper: https://gts3.org/assets/papers/2019/xu:janus-slides.pdf
Artifact: https://github.com/sslab-gatech/janus


Summary

(+) Sigenifcance: The authors address an important problem of kernel file system security. The bugs in file systems are security-critical and difficult to detect due to the complexity of both file systems and operating systems. The author present JANUS, a dedicated fuzzing technique for detecting bugs in the file system
(+) Novelty: The authors present an approach that needs to pay attention to the input of two dimensions at the same time (i.e., mutating metadata on a large image, while emitting image-directed file operations.)
(+) Soundness: Experiments are conducted on 8 file systems and found 90 bugs in Linux kernel, compared against Syzkaller.


Reading Notes

1. Introduction

Q: 測試內核中的文件系統(File system)有哪些挑戰?
A: 由於文件系統自身結構的複雜性以及它在操作系統中扮演角色的重要程度,決定了模糊文件系統與模糊普通二進制程序之間的大不同。文件系統完整運行需要兩個輸入:一是加載好的磁盤映像,二是在磁盤映像上的執行的各種文件操作。想要有效的對文件系統進行模糊測試,必須解決以下幾個問題:
文件系統以文件鏡像(image),文件鏡像的大小遠遠大於普通用戶態程序
在一個文件系統鏡像中,一般只有其中的元數據(metadata)會對文件系統的操作產生影響,普通的文件數據是無用的,而metadata只佔整個文件系統鏡像的1%左右,這導致模糊測試時對輸入的突變操作可能大部分是無效的。
有效的文件操作應該是基於運行時的文件系統的實際狀態的,而傳統的生成workloads的方法只和文件系統的初始狀態有關,和上下文操作無關,workloads的部分操作可能時無效的。因此在生成workloads的過程中,必須維持文件系統的狀態,基於之前的狀態來生成新的文件操作。
輸入空間有兩個維度,文件操作和文件系統鏡像之間是存在聯繫。Fuzzer需要同步的對這兩種輸入進行fuzz,而不像一般的Fuzzer那樣只考慮一種形式的輸入。
目前針對操作系統的Fuzzer爲了避免重置系統狀態導致的巨大開銷,在運行不同的workloads時,會複用之前的系統實例,這會使得在長時間運行後系統的行爲變的不可靠,從而使得很多crash不可被複現。

Q: 文件系統測試用例的構成?
A: 測試用例有三部分構成:元數據(metadata),一系列文件操作(program or workloads),文件系統的狀態(status)。

Q: 目前多研究現狀?
A: 在文件操作測試用例這方面,當前流行的內核模糊測試工具Syzkaller,是盲目的生成系統調用,並不考慮文件操作與磁盤映像上的文件系統之間的動態依賴性(比如syzkaller對那些已被重命名rename()或已刪除unlink()的舊路徑文件重複發出read()調用)。
當前的模糊器都依賴VM,QEMU,UML的實例,在其上運行目標文件系統,由於每次加載實例時間較長,於是通過重用實例節約時間,這也導致運行一定時間後,系統狀態變得不確定。甚至在一個崩潰出現後,由於經過了成千上萬次的調用,導致開發人員難以重現BUGs。
由於文件操作和文件系統映像之間是存在聯繫。Fuzzer需要同步的對這兩種輸入進行模糊測試,而當前的Fuzzer只考慮一種形式的輸入。

2. Approach

Q: 作者的方案?
A: 針對前面提出的挑戰,作者提出瞭如下方案:
因爲metadata只佔整個文件系統鏡像的1%左右,JANUS通過從文件系統鏡像中精確定位並提取metadata來解決第一個問題;
通過基於文件系統的運行時狀態來生成新的文件操作解決了第二問題;
專門提出了文件操作的變異方式,從而解決了第三個問題
同時探索兩個維度的輸入空間,從而解決第四個問題;
第五個問題主要是執行環境。

Q: JANUS的整體設計架構?
A: Overview如下圖所示
首先JANUS會根據不同類型的文件系統,對輸入的鏡像進行解析,從中定位並提取出對應的metadata,並得到文件系統的初始狀態status,然後生成一個打開文件的文件操作作爲初始的program,並更新program運行後的文件系統的可能狀態爲新的status。對seed input的解析結果構成一個集合(Corpus)。
之後從Corpus挑選出一個測例進行mutate。Metadata由Image mutator進行fuzz,生成新的metadata’;program交由Syscall fuzzer基於status進行fuzz,生成新的program’,以及對應的新狀態status’。
接着,JANUS會將metadata’,組裝成一個完整的文件系統鏡像,並重新計算相應的checksum。然後由一個用戶態的操作系統執行器,掛載這個鏡像,並執行program’,並把執行情況返回給引擎,如果這個測例是有價值的,比如其會使程序執行一條之前未被執行到的路徑,則這個測例會被加入到Corpus,否則這個測例將被拋棄。
最後,這個執行器每次運行新的program前都會重置,確保系統狀態不受之前操作的影響。
在這裏插入圖片描述
首先,測試引擎從初始corpus中取出一個測試用例,然後調用image mutator,採取常規的變異策略(和syzkaller策略一樣),比如位翻轉等,變異測試用例的元數據,完成以後,再根據記錄來重新計算好校驗和。此時,測試用例中的program保持不變,image status也保持不變,然後根據記錄的元數據偏移量,把這些元數據和未變異的用戶數據重新組成完整的磁盤映像。最後把完整的映像和相應的文件操作加載到EXECUTOR(基於linux kernel library建立,可測試文件系統的功能,在用戶空間中運行,這樣可以保證每次執行後,在可以忽略的時間內刷新內核,方便開發人員重現BUGs)中去執行。在評估中,設定模糊一個測試用例的磁盤映像環節重複進行256輪次(由人員指定),當有出現新的路徑覆蓋時,會把這個測試用例(包括元數據,program,image status)打包保存到corpus中(類似AFL風格的代碼覆蓋反饋),如無新的路徑發現,則開始對系統調用進行變異,取出相應的測試用例,元數據保持不變,調用syscall fuzzer對program進行變異,對於program裏那些調用的普通參數,採用和syzkaller變異它們相同的策略,它們和image status無關。對於program裏那些依賴文件系統運行上下文的敏感參數值,JANUS變異它們不僅考慮它們的預期值,更要根據image status來變異,例如,某個操作需要文件描述符爲對象,,syscall fuzzer隨機選擇一個正確類型的已打開的文件描述符作爲對象。此時,根據program裏的調用和原status,生成新的status,成爲新的測試用例。最後和前面一樣,把未改變的元數據和用戶數據組成完整的映像,在和program加載到executor中執行。128輪次以後,如有新的路徑發現,把這個新的測試用例保存到corpus中,如沒有,則開始增加新的文件操作到program中,元數據和原來的系統調用此時保持不變,在fuzzing 引擎結束後,依然需要更新image status,最後完整的映像加載到executor執行64輪次,如無新的覆蓋出現,此測試用例使命結束。然後選擇下一個測試用例,迭代進行。下圖是二維輸入的調度過程:
在這裏插入圖片描述
由於每次都在乾淨的內核上運行,當出現崩潰時,本文通過實現一個概念驗證器根據序列化的測試用例來生成一個帶有可編譯C程序的完整的磁盤映像,以便重現BUGs。
綜上看來,通過僅模糊元數據解決了輸入測試用例尺寸太大的問題;引入image status,根據status變異生成的相應的文件操作,已解決文件操作依賴上下文的問題;在每次變異元數據,根據記錄修正校驗和;在基於library OS生成的executor測試,在用戶空間裏運行,這樣解決了BUG重現問題。

Q: JANUS對兩個維度的輸入空間有什麼不同的變異策略
A: 由於JANUS關注兩個不同維度的輸入空間,對其分別制定了變異策略
對metadata的變異其他的fuzzer類似,JANUS會隨機的改變metadata中的某些字節,而不會去考慮metadata的具體語義。
對一系列文件操作的變異相對複雜。策略有兩種,一種是改變一系列文件操作中已有的某個操作的參數;另一種是在一系列文件操作的最後新增一個文件操作。文件操作的類型是隨機的,但是操作的文件對象和參數,是基於當前的status和一些系列人爲設定的規則生成的。這確保一系列文件操作是上下文有關的,並依賴於當前的文件系統狀態,能極大的減少無效操作。

3. Evaluation

  • Bug detection: 8個文件系統上進行了測試,最終發現了90個bug
  • Coverage: JANUS在代碼覆蓋率上也遠遠優於另一個系統內核Fuzzing工具Syzkaller。
  • Crash reproduce:實驗顯示根據JANUS生成的PoC,能復現其中90%左右的crash,而Syzkaller給出的PoC完全無法重現crash。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章