消毒殺菌劑

提振精神

消毒程式是用來偵測程式碼中特定類別錯誤的工具。 運作原則各有不同,但消毒程序通常 (但不一定) 依賴 某些形式的編譯時間檢測功能,以公開 發生錯誤 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) 初始化 將變數自動設為非零模式,找出與讀取相關的錯誤 而不必初始化的記憶體。
  • ShadowCallStackSafeStack 加強了 產生的程式碼

最後,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)。
  • 建構與來重現錯誤。
  • 後續調查的詳細資訊,以及 。
  • 提及相關變更, 例如本例中的「變更」,是為了修正 根本原因

發展藍圖

進行中的工作:

日後工作的領域:

  • ThreadSanitizer (TSan):偵測資料競爭。
  • 核心支援,可偵測並行錯誤。
  • 擴大 Rust 的清理程式支援,例如偵測記憶體安全錯誤 在 Rust unsafe {} 程式碼區塊中或 FFI 呼叫中 偵測未定義的行為錯誤
  • MemorySanitizer (MSan):偵測 未初始化的記憶體。

另請參閱:2021 年發展藍圖中的衛生器