從 Android 11 開始,對於 64 位元進程,在核心支援 ARM 頂位元組忽略 (TBI) 的裝置上,所有堆分配都在指標的頂字節中設定了實現定義的標記。當在釋放期間檢查該標籤時,任何修改該標籤的應用程式都會終止。這對於未來具有ARM 記憶體標記擴展(MTE) 支援的硬體是必要的。
忽略頂字節
ARM 的頂位元組忽略功能可用於所有 Armv8 AArch64 硬體中的 64 位元程式碼。此功能意味著硬體在存取記憶體時會忽略指標的最高位元組。
TBI 需要一個相容的核心來正確處理從使用者空間傳遞的標記指標。 4.14 (Pixel 4) 及更高版本的 Android 通用核心具有所需的TBI 修補程式。
核心中支援 TBI 的裝置會在進程啟動時動態偵測,並將與實作相關的標記插入到所有堆疊分配的指標的頂部位元組中。此後,將運行檢查以確保在釋放記憶體時標記沒有被截斷。
記憶體標記擴充準備就緒
ARM 的記憶體標記擴充 (MTE) 有助於解決記憶體安全問題。 MTE 的工作原理是標記堆疊、堆疊和全域變數上每個記憶體分配的第 56-59 個位址位元。硬體和指令集自動檢查每次記憶體存取時是否使用了正確的標籤。
如果 Android 應用程式在指標的最高位元組中錯誤地儲存訊息,則肯定會在支援 MTE 的裝置上崩潰。標記指針可以在 MTE 設備可用之前更輕鬆地檢測和拒絕指針最高位元組的錯誤使用。
開發者支持
如果您的應用程式崩潰並且系統提示您使用此鏈接,則可能意味著以下情況之一:
- 應用程式嘗試釋放未由系統堆分配器指派的指標。
- 您的應用程式中的某些內容修改了指標的最高位元組。指標的最高位元組無法修改,需要更改程式碼才能解決此問題。
錯誤使用或修改頂部位元組指標的範例。
- 指向特定類型的指標具有儲存在前 16 個位址位元中的應用程式特定元資料。
- 指標先轉換為 double,然後再轉換回來,從而失去低位址位元。
- 程式碼計算來自不同堆疊幀的局部變數位址之間的差異,作為測量遞歸深度的一種方法。
某些應用程式可能依賴在設定指標的最高位元組時行為不正確的庫。我們認識到,快速解決圖書館中的這些潛在問題可能並非易事。因此,使用targetSdkLevel < 30
的應用程式預設不會啟用指標標記。我們也為使用targetSdkLevel >= 30
建立的應用程式提供了逃生口,以緩解過渡期。
透過將以下內容新增至AndroidManifest.xml
檔案來使用逃生艙口:
<application android:allowNativeHeapPointerTagging="false"> ... </application>
這將停用您的應用程式的指標標記功能。請注意,這並不能解決根本的程式碼健康問題。這個逃生艙口將在 Android 的未來版本中消失,因為這種性質的問題將與MTE不相容。