Oznaczone wskaźniki

Począwszy od systemu Android 11, w przypadku procesów 64-bitowych wszystkie alokacje sterty mają znacznik zdefiniowany w implementacji ustawiony w górnym bajcie wskaźnika na urządzeniach z obsługą jądra dla ARM Top-byte Ignore (TBI). Każda aplikacja modyfikująca ten znacznik zostanie zakończona po sprawdzeniu znacznika podczas dezalokacji. Jest to konieczne w przypadku przyszłego sprzętu obsługującego rozszerzenie pamięci ARM (MTE).

Ignoruj ​​górny bajt

Funkcja ignorowania górnych bajtów ARM jest dostępna dla kodu 64-bitowego na całym sprzęcie Armv8 AArch64. Ta funkcja oznacza, że ​​sprzęt ignoruje górny bajt wskaźnika podczas uzyskiwania dostępu do pamięci.

TBI wymaga kompatybilnego jądra , które poprawnie obsługuje oznaczone wskaźniki przekazywane z przestrzeni użytkownika. Wspólne jądra systemu Android od wersji 4.14 (Pixel 4) i nowszych zawierają wymagane poprawki TBI .

Urządzenia obsługujące TBI w jądrze są dynamicznie wykrywane w momencie rozpoczęcia procesu, a znacznik zależny od implementacji jest wstawiany w górnym bajcie wskaźnika dla wszystkich alokacji sterty. Następnie sprawdzane jest, czy znacznik nie został obcięty podczas zwalniania pamięci.

Gotowość rozszerzenia znakowania pamięci

Rozszerzenie znacznika pamięci (MTE) firmy ARM pomaga rozwiązać problemy związane z bezpieczeństwem pamięci. MTE działa poprzez znakowanie 56-59 bitów adresu każdej alokacji pamięci na stosie, stercie i obiektach globalnych. Sprzęt i zestaw instrukcji automatycznie sprawdzają, czy przy każdym dostępie do pamięci użyto prawidłowego znacznika.

Aplikacje na Androida, które nieprawidłowo przechowują informacje w górnym bajcie wskaźnika, z pewnością zawiodą na urządzeniu obsługującym MTE . Oznaczone wskaźniki ułatwiają wykrywanie i odrzucanie nieprawidłowego użycia górnego bajtu wskaźnika, zanim urządzenia MTE będą dostępne.

Wsparcie programistów

Jeśli aplikacja uległa awarii i wyświetlił się monit o wyświetlenie tego linku, może to oznaczać jedną z następujących sytuacji:

  1. Aplikacja próbowała zwolnić wskaźnik, który nie został przydzielony przez systemowy alokator sterty.
  2. Coś w Twojej aplikacji zmodyfikowało górny bajt wskaźnika. Nie można modyfikować górnego bajtu wskaźnika i aby rozwiązać ten problem, należy zmienić kod.

Przykłady nieprawidłowego użycia lub modyfikacji wskaźnika górnego bajtu.

  • Wskaźniki do określonego typu mają metadane specyficzne dla aplikacji przechowywane w 16 pierwszych bitach adresu.
  • Wskaźnik rzutowany na wartość double, a następnie z powrotem, tracąc dolne bity adresu.
  • Kod obliczający różnicę między adresami zmiennych lokalnych z różnych ramek stosu w celu zmierzenia głębokości rekurencji.

Niektóre aplikacje mogą zależeć od bibliotek, które zachowują się niepoprawnie, gdy ustawiony jest górny bajt wskaźnika. Zdajemy sobie sprawę, że szybkie naprawienie podstawowych problemów w bibliotekach może nie być trywialne. W związku z tym aplikacje korzystające z targetSdkLevel < 30 nie będą miały domyślnie włączonego znakowania wskaźników. Zapewniamy również lukę ratunkową dla aplikacji zbudowanych z targetSdkLevel >= 30 aby ułatwić okres przejściowy.

Klapa ratunkowa jest używana po dodaniu następujących elementów do pliku AndroidManifest.xml :

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

Spowoduje to wyłączenie funkcji oznaczania wskaźników w Twojej aplikacji. Należy pamiętać, że nie rozwiązuje to podstawowego problemu ze stanem kodu. Ten luk awaryjny zniknie w przyszłych wersjach Androida, ponieważ problemy tego rodzaju będą niekompatybilne z MTE .