Pointeurs marqués

À partir d'Android 11, pour les processus 64 bits, toutes les allocations de tas ont une balise définie par l'implémentation définie dans l'octet supérieur du pointeur sur les appareils avec prise en charge par le noyau pour ARM Top-byte Ignore (TBI). Toute application qui modifie cette balise est terminée lorsque la balise est vérifiée lors de la désallocation. Cela est nécessaire pour le futur matériel prenant en charge ARM Memory Tagging Extension (MTE).

Ignorer le premier octet

La fonctionnalité Top-byte Ignore d'ARM est disponible pour le code 64 bits dans tout le matériel Armv8 AArch64. Cette fonctionnalité signifie que le matériel ignore l'octet de poids fort d'un pointeur lors de l'accès à la mémoire.

TBI nécessite un noyau compatible qui gère correctement les pointeurs balisés transmis depuis l'espace utilisateur. Les noyaux communs Android à partir de la version 4.14 (Pixel 4) et versions ultérieures comportent les correctifs TBI requis.

Les périphériques prenant en charge TBI dans le noyau sont détectés dynamiquement au démarrage du processus et une balise dépendante de l'implémentation est insérée dans l'octet de haut du pointeur pour toutes les allocations de tas. Après cela, une vérification est effectuée pour garantir que la balise n'a pas été tronquée lors de la désallocation de la mémoire.

Préparation de l'extension de marquage de mémoire

L'extension de marquage de mémoire (MTE) d'ARM permet de résoudre les problèmes de sécurité de la mémoire. MTE fonctionne en marquant les 56e à 59e bits d'adresse de chaque allocation de mémoire sur la pile, le tas et les variables globales. Le matériel et le jeu d'instructions vérifient automatiquement que la balise correcte est utilisée à chaque accès à la mémoire.

Les applications Android qui stockent de manière incorrecte des informations dans l'octet supérieur du pointeur sont garanties de ne pas fonctionner sur un appareil compatible MTE . Les pointeurs balisés facilitent la détection et le rejet des utilisations incorrectes de l'octet de poids supérieur du pointeur avant que les périphériques MTE ne soient disponibles.

Assistance aux développeurs

Si votre application plante et que ce lien vous est demandé, cela peut signifier l'une des situations suivantes :

  1. L'application a tenté de libérer un pointeur qui n'était pas alloué par l'allocateur de tas du système.
  2. Quelque chose dans votre application a modifié l'octet de haut d'un pointeur. L'octet supérieur du pointeur ne peut pas être modifié et votre code doit être modifié pour résoudre ce problème.

Exemples de pointeur d'octet supérieur mal utilisé ou modifié.

  • Les pointeurs vers un type particulier ont des métadonnées spécifiques à l'application stockées dans les 16 premiers bits d'adresse.
  • Un pointeur converti en double puis en arrière, perdant les bits d'adresse inférieurs.
  • Code calculant la différence entre les adresses des variables locales de différentes trames de pile afin de mesurer la profondeur de récursion.

Certaines applications peuvent dépendre de bibliothèques qui se comportent incorrectement lorsque l'octet de poids supérieur du pointeur est défini. Nous reconnaissons qu’il n’est peut-être pas trivial de résoudre rapidement ces problèmes sous-jacents dans les bibliothèques. En tant que telles, les applications qui utilisent targetSdkLevel < 30 n’auront pas le marquage de pointeur activé par défaut. Nous fournissons également une trappe de secours pour les applications créées avec targetSdkLevel >= 30 afin de faciliter la période de transition.

La trappe d'évacuation est utilisée en ajoutant ce qui suit à votre fichier AndroidManifest.xml :

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

Cela désactivera la fonctionnalité de marquage du pointeur pour votre application. Veuillez noter que cela ne résout pas le problème de santé sous-jacent du code. Cette trappe de secours disparaîtra dans les futures versions d'Android, car les problèmes de cette nature seront incompatibles avec MTE .