Google致力於提高黑人社區的種族平等。 怎麼看。
本頁面由 Cloud Translation API 翻譯而成。
Switch to English

整數溢出消毒

意外的整數溢出會導致內存損壞或與內存訪問或內存分配相關聯的變量中的信息洩露漏洞。為了解決這個問題,我們添加了Clang的UndefinedBehaviorSanitizer (UBSan)有符號和無符號整數溢出消毒劑,以加強 Android 7.0中的媒體框架 。在Android 9中,我們擴展了UBSan,以涵蓋更多組件並改進了其對構建系統的支持。

這樣做的目的是在可能發生溢出的算術運算/指令周圍添加檢查,以在發生溢出時安全地中止進程。這些清除程序可以緩解整個類別的內存損壞和信息洩露漏洞,其中根本原因是整數溢出,例如原始的Stagefright漏洞。

實例和來源

整數溢出清理(IntSan)由編譯器提供,並在編譯期間將工具添加到二進製文件中以檢測算術溢出。默認情況下,在整個平台的各個組件中都啟用了此功能,例如/platform/external/libnl/Android.bp

實作

IntSan使用UBSan的有符號和無符號整數溢出消毒劑。在每個模塊級別啟用此緩解措施。它有助於確保Android的關鍵組件的安全,因此不應禁用它。

我們強烈建議您為其他組件啟用Integer Overflow Sanitization。理想的候選者是特權本機代碼或解析不受信任的用戶輸入的本機代碼。與清理程序相關的性能開銷很小,這取決於代碼的用法和算術運算的普遍性。預期開銷百分比很小,並測試性能是否值得關注。

在makefile中支持IntSan

要在makefile中啟用IntSan,請添加:

LOCAL_SANITIZE := integer_overflow
# Optional features
LOCAL_SANITIZE_DIAG := integer_overflow
LOCAL_SANITIZE_BLACKLIST := modulename_blacklist.txt
  • LOCAL_SANITIZE採用逗號分隔的消毒劑列表, integer_overflow是帶有默認黑名單的單個有符號和無符號整數溢出消毒劑的預包裝選項集。
  • LOCAL_SANITIZE_DIAG為消毒LOCAL_SANITIZE_DIAG打開診斷模式。僅在測試期間使用診斷模式,因為這不會在溢出時中止,從而完全消除了緩解措施的安全性優勢。有關其他詳細信息,請參見故障排除
  • LOCAL_SANITIZE_BLACKLIST允許您指定黑名單文件,以防止對功能和源文件進行清理。有關其他詳細信息,請參見故障排除

如果要進行更精細的控制,請使用一個或兩個標誌分別啟用消毒器:

LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow
LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow

在藍圖文件中支持IntSan

要在藍圖文件(例如/platform/external/libnl/Android.bp啟用整數溢出清理,請添加:

   sanitize: {
      integer_overflow: true,
      diag: {
          integer_overflow: true,
      },
      blacklist: "modulename_blacklist.txt",
   },

與make文件一樣, integer_overflow屬性是預打包的一組選項,用於帶有默認黑名單的單個有符號和無符號整數溢出清除程序

diag屬性集啟用消毒器的診斷模式。僅在測試期間使用診斷模式。診斷模式不會在溢出時中止,這完全抵消了用戶構建中的緩解措施的安全性優勢。有關其他詳細信息,請參見故障排除

blacklist屬性允許指定黑名單文件,該文件允許開發人員阻止對功能和源文件進行清理。有關其他詳細信息,請參見故障排除

要單獨啟用消毒劑,請使用:

   sanitize: {
      misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"],
      diag: {
          misc_undefined: ["signed-integer-overflow",
                           "unsigned-integer-overflow",],
      },
      blacklist: "modulename_blacklist.txt",
   },

故障排除

如果要在新組件中啟用整數溢出清理,或依賴已進行整數溢出清理的平台庫,則可能會遇到一些良性整數溢出導致中止的問題。您應該在啟用消毒的情況下測試組件,以確保可以消除良性溢出。

要查找由用戶版本中的清理導致的中止,請搜索SIGABRT崩潰,並顯示中止消息,指示UBSan捕獲了溢出,例如:

pid: ###, tid: ###, name: Binder:###  >>> /system/bin/surfaceflinger <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'ubsan: sub-overflow'

堆棧跟踪應包括導致中止的函數,但是,內聯函數中發生的溢出在堆棧跟踪中可能並不明顯。

為了更容易地確定根本原因,請在庫中啟用診斷以觸發異常終止並嘗試重現該錯誤。 啟用診斷後,該過程將不會中止 ,而是將繼續運行。不中止有助於最大化特定執行路徑中良性溢出的次數,而無需在修復每個錯誤之後重新編譯。診斷產生一條錯誤消息,其中包括導致中止的行號和源文件:

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')

一旦找到有問題的算術運算,請確保溢出是良性的和預期的(例如,不涉及安全問題)。您可以通過以下方法解決消毒劑中止的問題:

您應該使用最精細的解決方案。例如,具有許多算術運算和單個溢出運算的大型函數應重構單個運算符,而不是將整個函數列入黑名單。

可能導致良性溢出的常見模式包括:

建議開發人員確保在禁用消毒之前,在消毒器檢測到溢出的情況下,它確實是良性的,沒有意外的副作用或安全隱患。

禁用IntSan

您可以使用黑名單或函數屬性禁用IntSan。僅當重構代碼不合理或性能開銷有問題時才謹慎禁用。

有關使用功能屬性黑名單文件格式禁用IntSan的更多信息,請參見上游Clang文檔。應通過使用指定目標消毒劑的節名稱將黑名單限定在特定的消毒劑範圍內,以避免影響其他消毒劑。

驗證方式

當前,沒有專門針對Integer Overflow Sanitization的CTS測試。相反,請確保在啟用或未啟用IntSan的情況下通過CTS測試,以驗證它不會影響設備。