記憶體偵錯與緩解

Android 支援多項用於記憶體偵錯的工具。每項工具各有優缺點,因此請詳閱以下說明,判斷哪一項最適合您。本文件會以簡要文字概略介紹這些可用工具,方便您掌握該深入探討哪一項工具。各項工具另備有專屬文件,歡迎瞭解詳細內容。

重點摘要

  • 盡可能使用記憶體安全語言,避免發生記憶體錯誤
  • 一律使用 PAC/BTI 緩解 ROP/JOP 攻擊
  • 一律使用 GWP-ASan 偵測實際工作環境中的罕見記憶體錯誤
  • 使用 HWASan 偵測測試期間的記憶體錯誤
  • 支援 MTE 的裝置在 2023 年尚未普及,但如果您能在實際工作環境中偵測錯誤,請使用這項工具
  • 只有在無可選擇的情況下,才在測試期間使用 ASan

記憶體安全語言

記憶體安全語言是完全避免及減少記憶體錯誤的唯一方法。本頁所述的其他工具可提高記憶體不安全程式碼的穩定性,但使用記憶體安全語言才能完全排除這類問題。

Android 正式支援的記憶體安全語言為 Java 和 Kotlin。大多數的 Android 應用程式都能使用這兩種語言輕鬆開發。

儘管如此,有些應用程式開發人員會發布以 Rust 編寫的程式碼,而閱讀這個頁面的使用者基於可攜性和/或效能,卻很可能需要使用原生程式碼。Rust 是 Android 的最佳記憶體安全原生程式碼。如果您採用這個做法,NDK 團隊不一定都能幫您解決遇到的問題,但我們希望能得知這些問題

PAC/BTI

指標驗證和分支目標識別 (又稱為 PAC/BTI) 是適合用於實際工作環境的緩解工具。雖然兩者所用技術不同,但都是由相同的編譯器旗標控管,因此一律會搭配使用。

這些功能會在舊版裝置上使用免人工管理的新指示,因此可回溯相容先前不支援的裝置。此外,裝置也必須使用夠新的核心和 OS 版本。您可以在 /proc/cpuinfo 中查看 pacabti,瞭解硬體和核心是否夠新。Android 12 (API 31) 提供必要的使用者空間支援。

優點:

  • 可在所有版本中啟用,不會對舊版裝置或核心造成問題 (但請務必在「確實」支援這項工具的裝置/核心/OS 組合上實際完成測試!)

缺點:

  • 僅適用於 64 位元應用程式
  • 如果裝置不支援這項工具,就無法減少錯誤
  • 1% 的程式碼大小負擔

GWP-ASan

GWP-ASan 可用來偵測欄位中的記憶體錯誤,但取樣率過低,無法有效減少錯誤。

優點:

  • 沒有大量的 CPU 或記憶體負擔
  • 容易部署:無須重新建構原生程式碼
  • 適用於 32 位元應用程式

缺點:

  • 取樣率偏低,需要大量使用者才能有效找出錯誤
  • 只偵測堆積錯誤,而非堆疊錯誤

HWASan

如要在測試期間找出記憶體錯誤,Hardware Address Sanitizer (又稱為 HWASan) 是最適合的選擇。這項工具搭配自動化測試時最實用,特別是在執行模糊測試時。不過,視應用程式效能需求而定,也可用於高階手機的 Dogfood 測試設定。

優點:

  • 沒有偽陽性
  • 可偵測 ASan 無法偵測到的其他錯誤類別 (傳回後使用堆疊)
  • 偽陰性率低於 MTE (1/256 與 1/16)
  • 與最接近的 ASan 相比,記憶體負擔較低

缺點:

  • 會耗用大量資源:CPU (可達 100%)、程式碼大小 (可達 50%) 和記憶體 (10% 至 35%)
  • 在 API 34 和 NDK r26 之前,必須刷新與 HWASan 相容的映像檔
  • 僅適用於 64 位元應用程式

MTE

Memory Tagging Extension (又稱為 MTE) 是費用較低的 HWASan 替代方案,適合用於實際工作環境。如果您有可測試 MTE 版本的硬體,請啟用這項工具。

優點:

  • 對許多應用程式來說負擔夠低,可容許在實際工作環境中使用
  • 沒有偽陽性
  • 無須重新建構程式碼就能偵測堆積錯誤 (但偵測堆疊錯誤時仍然需要)

缺點:

  • 在 2023 年,支援 MTE 的裝置尚未上市
  • 相較於 HWASan 的 1/256,MTE 的偽陰性率為 1/16
  • 僅適用於 64 位元應用程式
  • 必須建構不同的程式庫,才能同時指定支援 MTE 和不支援 MTE 的裝置

ASan

Address Sanitizer (又稱為 ASan) 是最早且最普遍使用的工具。如要在測試期間找出記憶體錯誤,以及針對只會影響舊裝置的問題偵錯,且沒有其他工具可用時,這項工具就能派上用場。在可能情況下,請盡量使用 HWASan

優點:

  • 普遍可用,適用於 KitKat 等舊裝置
  • 如正確使用,不會出現偽陽性或偽陰性

缺點:

  • 難以正確建構及封裝
  • 在所有選項中最耗資源:佔用 CPU 可達 100%,程式碼大小可達 50%,記憶體用量可達 100%
  • 已停止支援
  • 有無法修正的已知錯誤