標記指針

從 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 設備可用之前更輕鬆地檢測和拒絕指針最高位元組的錯誤使用。

開發者支持

如果您的應用程式崩潰並且系統提示您使用此鏈接,則可能意味著以下情況之一:

  1. 應用程式嘗試釋放未由系統堆分配器指派的指標。
  2. 您的應用程式中的某些內容修改了指標的最高位元組。指標的最高位元組無法修改,需要更改程式碼才能解決此問題。

錯誤使用或修改頂部位元組指標的範例。

  • 指向特定類型的指標具有儲存在前 16 個位址位元中的應用程式特定元資料。
  • 指標先轉換為 double,然後再轉換回來,從而失去低位址位元。
  • 程式碼計算來自不同堆疊幀的局部變數位址之間的差異,作為測量遞歸深度的一種方法。

某些應用程式可能依賴在設定指標的最高位元組時行為不正確的庫。我們認識到,快速解決圖書館中的這些潛在問題可能並非易事。因此,使用targetSdkLevel < 30的應用程式預設不會啟用指標標記。我們也為使用targetSdkLevel >= 30建立的應用程式提供了逃生口,以緩解過渡期。

透過將以下內容新增至AndroidManifest.xml檔案來使用逃生艙口:

  <application android:allowNativeHeapPointerTagging="false">
  ...
  </application>

這將停用您的應用程式的指標標記功能。請注意,這並不能解決根本的程式碼健康問題。這個逃生艙口將在 Android 的未來版本中消失,因為這種性質的問題將與MTE不相容。