自 Android 11 起,對於 64 位元程序,所有堆積分配都會在指標的位元組頂端設定實作定義的標記,前提是裝置的核心支援 ARM 位元組頂端忽略 (TBI)。在釋放資源期間檢查此標記時,任何修改此標記的應用程式都會遭到終止。這項操作對於日後支援 ARM Memory Tagging Extension (MTE) 的硬體裝置而言是必要的。
忽略位元組頂端
ARM 的 Top-byte Ignore 功能適用於所有 Armv8 AArch64 硬體的 64 位元程式碼。這項功能表示硬體會在存取記憶體時忽略指標的頂端位元組。
TBI 需要相容的核心,才能正確處理從使用者空間傳遞的標記指標。Android 通用核心 4.14 (Pixel 4) 以上版本提供必要的 TBI 修補程式。
系統會在處理程序開始時動態偵測核心中支援 TBI 的裝置,並在所有堆積配置的指標頂端位元組中插入實作相關的標記。之後,系統會執行檢查,確保在釋放記憶體時,標記不會遭到截斷。
記憶體標記擴充功能的準備就緒狀態
ARM 的 Memory Tagging Extension (MTE) 可協助解決記憶體安全性問題。MTE 的運作方式是標記堆疊、堆積和全域中每個記憶體配置的 56 到 59 位元位址。硬體和指令集會自動檢查每次存取記憶體時是否使用正確的標記。
如果 Android 應用程式在指標的位元組頂端錯誤儲存資訊,則保證會在支援 MTE 的裝置上發生錯誤。標記指標可在 MTE 裝置可用之前,更輕鬆地偵測及拒絕指標頂端位元組的錯誤用途。
開發人員支援
如果應用程式發生當機,系統會顯示這個連結,表示發生下列情況之一:
- 應用程式嘗試釋放系統堆積分配器未分配的指標。
- 應用程式中的某項內容修改了指標的位元組頂端。指標的頂層位元組無法修改,因此您必須變更程式碼才能修正這個問題。
頂位元指標遭到錯誤使用或修改的範例。
- 指向特定類型的指標會在前 16 個位址位元中儲存應用程式專屬的中繼資料。
- 指標轉換為雙精度,然後再轉回,因此失去較低位址位元。
- 程式碼會計算不同堆疊框架中本機變數的位址之間的差異,以此評估遞迴深度。
部分應用程式可能會依附在指標頂端位元設定時,會導致程式庫行為不正確。我們瞭解,要快速修正程式庫中的這些潛在問題可能不容易。因此,使用 targetSdkLevel < 30
的應用程式預設不會啟用指標標記。我們也為使用 targetSdkLevel >= 30
建構的應用程式提供逃逸機制,以便在轉換期間順利過渡。
如要使用逃逸門,請在 AndroidManifest.xml
檔案中新增下列內容:
<application android:allowNativeHeapPointerTagging="false"> ... </application>
這會為應用程式停用「指標標記」功能。這不會解決基礎程式碼的執行狀況問題。這項逃逸機制會在日後的 Android 版本中消失,因為這類問題與 MTE 不相容。