Markierte Zeiger

Ab Android 11 verfügen alle Heap-Zuweisungen für 64-Bit-Prozesse über ein durch die Implementierung definiertes Tag im obersten Byte des Zeigers auf Geräten mit Kernel-Unterstützung für ARM Top-Byte Ignore (TBI). Jede Anwendung, die dieses Tag ändert, wird beendet, wenn das Tag während der Freigabe überprüft wird. Dies ist für zukünftige Hardware mit ARM Memory Tagging Extension (MTE)-Unterstützung erforderlich.

Top-Byte ignorieren

Die Top-Byte-Ignorierungsfunktion von ARM ist für 64-Bit-Code in der gesamten Armv8 AArch64-Hardware verfügbar. Diese Funktion bedeutet, dass die Hardware beim Zugriff auf den Speicher das oberste Byte eines Zeigers ignoriert.

TBI erfordert einen kompatiblen Kernel , der vom Userspace übergebene getaggte Zeiger korrekt verarbeitet. Android Common Kernels ab 4.14 (Pixel 4) und höher verfügen über die erforderlichen TBI-Patches .

Geräte mit TBI-Unterstützung im Kernel werden zum Prozessstartzeitpunkt dynamisch erkannt und für alle Heap-Zuweisungen wird ein implementiertes abhängiges Tag in das oberste Byte des Zeigers eingefügt. Anschließend wird eine Prüfung durchgeführt, um sicherzustellen, dass das Tag beim Freigeben des Speichers nicht abgeschnitten wurde.

Bereitschaft der Speicher-Tagging-Erweiterung

Die Memory Tagging Extension (MTE) von ARM hilft bei der Lösung von Speichersicherheitsproblemen. MTE markiert das 56.–59. Adressbit jeder Speicherzuordnung auf dem Stack, Heap und Globals. Die Hardware und der Befehlssatz prüfen bei jedem Speicherzugriff automatisch, ob das richtige Tag verwendet wird.

Android-Apps, die fälschlicherweise Informationen im obersten Byte des Zeigers speichern , funktionieren auf einem MTE-fähigen Gerät garantiert nicht . Markierte Zeiger erleichtern das Erkennen und Zurückweisen falscher Verwendungen des obersten Bytes des Zeigers, bevor MTE-Geräte verfügbar sind.

Entwicklerunterstützung

Wenn Ihre App abstürzt und Sie mit diesem Link dazu aufgefordert werden, kann dies eine der folgenden Ursachen haben:

  1. Die Anwendung hat versucht, einen Zeiger freizugeben, der nicht vom Heap-Zuordner des Systems zugewiesen wurde.
  2. Etwas in Ihrer App hat das oberste Byte eines Zeigers geändert. Das oberste Byte des Zeigers kann nicht geändert werden und Ihr Code muss geändert werden, um dieses Problem zu beheben.

Beispiele für die falsche Verwendung oder Änderung des Top-Byte-Zeigers.

  • Zeiger auf einen bestimmten Typ verfügen über anwendungsspezifische Metadaten, die in den oberen 16 Adressbits gespeichert sind.
  • Ein Zeiger, der nach Double und dann zurück umgewandelt wird, wobei die unteren Adressbits verloren gehen.
  • Code, der die Differenz zwischen den Adressen lokaler Variablen aus verschiedenen Stapelrahmen berechnet, um die Rekursionstiefe zu messen.

Einige Anwendungen sind möglicherweise auf Bibliotheken angewiesen, die sich falsch verhalten, wenn das oberste Byte des Zeigers gesetzt ist. Wir sind uns bewusst, dass es möglicherweise nicht trivial ist, diese zugrunde liegenden Probleme in Bibliotheken schnell zu beheben. Daher ist bei Anwendungen, die targetSdkLevel < 30 verwenden, das Zeiger-Tagging nicht standardmäßig aktiviert. Wir bieten außerdem eine Notluke für Anwendungen, die mit targetSdkLevel >= 30 erstellt wurden, um den Übergangszeitraum zu vereinfachen.

Die Notluke wird verwendet, indem Sie Folgendes zu Ihrer AndroidManifest.xml Datei hinzufügen:

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

Dadurch wird die Pointer-Tagging-Funktion für Ihre Anwendung deaktiviert. Bitte beachten Sie, dass dadurch das zugrunde liegende Problem mit der Codegesundheit nicht behoben wird. Diese Notluke wird in zukünftigen Android-Versionen verschwinden, da Probleme dieser Art nicht mit MTE kompatibel sein werden.