提振精神
消毒程式是用來偵測程式碼中特定類別錯誤的工具。 運作原則各有不同,但消毒程序通常 (但不一定) 依賴 某些形式的編譯時間檢測功能,以公開 發生錯誤 Fuchsia 運用各種消毒液找出及診斷危險的錯誤 不易找到的網頁
清理器可透過建構時間旗標啟用。持續執行清理程式版本 在 Fuchsia 的持續整合 (CI) 和 Commit Queue (CQ) 中練習,以及 為 Fuchsia C/C++ 和 Rust 開發人員提供服務。
一般來說,開發人員不需採取特殊行動,就能受益於掃毒程式。 如此一來,只有在偵測到錯誤時,才需要留意消毒液。 但須遵守特定限制。繼續閱讀,瞭解什麼是消毒液 以及使用方式
支援的消毒液
Fuchsia 目前支援下列消毒液:
- AddressSanitizer (ASan) 會偵測 範圍外的存取權,可在免付費 / 回傳 / 範圍後使用,以及重複釋放。
- LeakSanitizer (LSan) 會偵測記憶體流失問題。 LeakSanitizer 的運作方式為檢查作業的保育垃圾收集器 以免發生流失無法透過參照根層級存取的任何配置 (執行緒的堆疊、執行緒註冊、全域變數及 執行緒本機變數) 則會視為外洩。
- ThreadSanitizer (TSan) 可偵測資料競爭 (僅限主機)。
- UndefinedBehaviorSanitizer (UBSan) 偵測 解決特定問題。
Zircon 核心支援下列消毒行為:
- 實體記憶體管理工具 (PMM) 檢查工具 (
pmm_checker
) 偵測到 使用已釋放的錯誤和儲存的《數位市場法》 - Kernel AddressSanitizer (KASan) 將 AddressSanitizer 延伸至核心 開發程式碼
- Lockdep 是執行階段鎖定驗證工具,可偵測鎖定危險 例如死結
系統預設會新增下列 C/C++ 編譯選項,用於偵測 避免在執行階段發生錯誤:
-ftrivial-auto-var-init=pattern
(請參閱 RFC) 初始化 將變數自動設為非零模式,找出與讀取相關的錯誤 而不必初始化的記憶體。- ShadowCallStack 和 SafeStack 加強了 產生的程式碼
最後,Fchsia 會使用 libFuzzer 和 運用 syzkaller 處理涵蓋率導向 模糊測試。模糊效果和消毒劑類似 嘗試在執行階段中公開程式碼中的錯誤,而這些錯誤通常用於 。模糊劑和消毒劑 將實際環境程式碼強制執行成為可能公開錯誤的路徑。
支援的設定
目前,我們支援本機建構作業,以及在 CI/CQ 中, 以下設定:
bringup.x64
bringup.arm64
core.x64
core.arm64
zbi_tests.x64
zbi_tests.arm64
此外,消毒程式也適用於主機工具。
上述所有測試都是在 qemu 進行 CI/CQ 測試 和 Intel NUC。其他平台並未使用消毒液測試 資源和容量問題,不過您可以在這些平台上執行本機測試 利用下文的建構工作流程。
//vendor
中定義的設定其他試用工作可能會顯示於
Gerrit 和 CI 控制台中的登入使用者分別登入。尋找設定
名稱中有-asan
。
上述清理程式適用於 C/C++ 程式碼。另外,LSan 套用至 Rust 程式碼,用於偵測「Rust 記憶體流失」。
排解 Sanitizer 問題
建構
Fuchsia 平台建構作業 (樹狀結構內)
如要重現掃毒版本,您可以使用建構變數啟用掃毒程式:
fx set product --variant asan-ubsan --variant host_asan-ubsan
此外,您也可以只檢測特定二進位檔:
fx set product --variant asan-ubsan/executable_name
若要在本機上測試 裝置無法容納完整檢測的硬體。
具體來說,如要偵測核心程式碼中的釋放後錯誤,您需要 啟用核心 PMM 檢查工具。
樹狀結構式建構
使用 Fuchsia 工具鍊進行編譯時,只要傳送
-fsanitize=
標記,指出要使用的消毒液。
請參閱編譯器說明文件。
使用檢測元件建立 Fuchsia 套件時,您需要 請確保套件包含所有執行階段依附元件,包括 Sanitizer 執行階段,這類執行階段是 Clang 工具鍊的一部分,且 檢測的 C 程式庫 (隨附於 Fuchsia SDK 中) 建立在 sysroot 之下
測試
照常在您的本機工作流程中測試,
已啟用的消毒液 (試用工作的名稱包含 asan
)。如果掃毒程式偵測到
問題之後,相關訊息將會列印至含有
下列字串:
ERROR: AddressSanitizer
ERROR: LeakSanitizer
SUMMARY: UndefinedBehaviorSanitizer
WARNING: ThreadSanitizer
在這些訊息之後,您即可找到堆疊追蹤,瞭解
並指出問題原因及根本原因您可以在以下位置找到這些郵件:
fx log
。
請注意,觸發清理作業的測試可能仍顯示為「通過」。 Sanitizer 問題不會列為測試失敗。
消毒程式偵測到的問題通常也具有類似的根本原因。您 只要搜尋 Fuchsia 錯誤,即可找到先前作品的參考資源 清除掃毒工具輸出內容中的幾個關鍵字
已知問題
#[should_panic]
Fuchsia 的 Rust 會在 panic!
上建構取消。這對使用者來說
縮減二進位檔的大小但有個可惜的副作用是測試
#[should_panic]
屬性可能會錯誤偵測記憶體流失情形。這些測試會
系統預期恐慌,接著在不放鬆的情況下退出,代表
堆積分配量。LeakSanitizer
以免發生記憶體流失的問題
如果這個問題會影響您的測試,您可以透過下列方式在 Sanitizer 版本中停用測試: 請參考這個範例。
請參閱:問題 88496:Rpanic 觸發外洩 leaksanitizer
最佳做法
確認程式碼經過測試
Sanitizer 在執行階段會公開錯誤。除非程式碼執行 (例如測試中) 或完全以 CI/CQ 的演練作業為基礎 這些特性將無法公開在程式碼中的錯誤。
確保程式碼的掃毒程式覆蓋範圍的最佳方式,就是確保 具備相同設定的涵蓋範圍參閱測試指南 涵蓋率
不要在程式碼中隱藏消毒液
某些建構目標可能會抑制清除工具。最常見的原因是 用於解決衛生支援前推出前的問題,尤其是 。
抑制的衛生器應視為技術負債,因為這類消毒不僅能夠隱藏舊的 但防止您發現程式碼出現新錯誤。 理想情況下,不應新增抑製或現有的抑制 並修正潛在錯誤
您可以編輯定義於物件的 BUILD.gn
檔案,藉此隱藏防毒液
您的執行檔目標如下:
executable("please_fix_the_bugs") {
...
# TODO(https://fxbug.dev/42074368): delete the below and fix the memory bug.
deps += [ "//build/config/sanitizers:suppress-asan-stack-use-after-return" ]
# TODO(https://fxbug.dev/42074368): delete the below and fix the memory bug.
deps += [ "//build/config/sanitizers:suppress-asan-container-overflow" ]
# TODO(https://fxbug.dev/42074368): delete the below and fix the memory leak.
deps += [ "//build/config/sanitizers:suppress-lsan.DO-NOT-USE-THIS" ]
}
以上範例示範如何隱藏所有消毒液。不過, 多數抑製造成故障的消毒液請追蹤抑制情況 ,並在上述步驟中參照問題。
另一種停用消毒液的常見方法如下:
executable("too_slow_when_built_with_asan") {
...
exclude_toolchain_tags = [ "asan" ]
}
上述兩個範例都隱藏整個可執行檔的精細程度。 如需更精細的抑制功能,您可以偵測裝置是否存在消毒液 再也不是件繁重乏味的工作舉例來說,在特定測試中隱藏消毒液時,這項功能就能派上用場 但不廣泛例如,刻意達成的測試 將引發記憶體錯誤,並測試掃毒程式執行階段本身。
如果是 C/C++,請參閱:
針對 Rust,您可以按照以下模式:
#[cfg(test)]
mod tests {
#[test]
// TODO(https://fxbug.dev/42074368): delete the below and fix the leak
#[cfg_attr(feature = "variant_asan", ignore)]
fn test_that_leaks() {
// ...
}
}
測試不穩定性
如果測試行為下的程式碼為 非確定性舉例來說,記憶體流失只有在特定競爭中才會發生 條件。如果掃毒程式發生錯誤,請參閱測試 攝氏的不悅。
回報錯誤
遇到掃毒問題時,請回報錯誤,並附上所有 有問題的疑難排解資訊
範例:問題 73214:blobfs 中的 ASAN use-after-scope
錯誤報告內含:
- 掃毒程式提供的錯誤 (本例中為 ASan)。
- 建構與來重現錯誤。
- 後續調查的詳細資訊,以及 。
- 提及相關變更, 例如本例中的「變更」,是為了修正 根本原因
發展藍圖
進行中的工作:
- 硬體加速 AddressSanitizer (hwasan): 大幅降低 Asan 的記憶體負擔 支援 RAM 受限裝置,並致力於縮小 導入硬體的獨立程式碼 另請參閱:RFC-0143: Userspace Top-Byte-Ignore。
- GWP-ASan:這項功能目前尚在進行 示範瞭如何使用這個 asan 取樣版本偵測 ] 欄位。
- 透過 syscalls 進行涵蓋範圍性核心模糊化。
日後工作的領域:
- ThreadSanitizer (TSan):偵測資料競爭。
- 核心支援,可偵測並行錯誤。
- 擴大 Rust 的清理程式支援,例如偵測記憶體安全錯誤
在 Rust
unsafe {}
程式碼區塊中或 FFI 呼叫中 偵測未定義的行為錯誤 - MemorySanitizer (MSan):偵測 未初始化的記憶體。
另請參閱:2021 年發展藍圖中的衛生器。