AddressSanitizer avec assistance matérielle

Consultez Comprendre les rapports HWASan pour savoir comment lire les plantages HWASan.

HWASan (Hardware-assisted AddressSanitizer) est un outil de détection des erreurs de mémoire semblable à AddressSanitizer. HWASan utilise beaucoup moins de RAM que ASan, ce qui le rend adapté à la désinfection de l'ensemble du système. HWASan n'est disponible que sur Android 10 ou version ultérieure, et uniquement sur du matériel AArch64.

Bien qu'il soit principalement utile pour le code C/C++, HWASan peut également aider à déboguer le code Java qui provoque des plantages en C/C++ utilisés pour implémenter des interfaces Java. Il est utile, car il détecte les erreurs de mémoire lorsqu'elles se produisent et vous dirige directement vers le code responsable.

Vous pouvez flasher des images HWASan prédéfinies sur les appareils Pixel compatibles à partir de ci.android.com (instructions de configuration détaillées).

Comparé à la version classique d'ASan, HWASan offre les avantages suivants :

  • Surcharge processeur similaire (environ 2 fois)
  • Surcharge de la taille du code similaire (40–50 %)
  • Surcharge de RAM beaucoup plus faible (10 à 35 %)

HWASan détecte le même ensemble de bugs qu'ASan :

  • Débordement positif/négatif de la pile et du tampon de tas de mémoire
  • Bugs "use-after-free" au niveau des tas de mémoire
  • Utilisation de la pile en dehors du champ d'application
  • Bugs de type "double free"/"wild free"

De plus, HWASan détecte l'utilisation de la pile après le retour.

HWASan (comme ASan) est compatible avec UBSan. Les deux peuvent être activés sur une cible en même temps.

Détails et limites d'implémentation

HWASan est basé sur l'approche de taggage de mémoire, dans laquelle une petite valeur de tag aléatoire est associée à la fois à des pointeurs et à des plages d'adresses mémoire. Pour qu'un accès à la mémoire soit valide, le pointeur et les balises de mémoire doivent correspondre. HWASan s'appuie sur la fonctionnalité ARMv8 Top Byte Ignore (TBI), également appelée tagging d'adresses virtuelles, pour stocker la balise de pointeur dans les bits les plus élevés de l'adresse.

Pour en savoir plus sur la conception de HWASan, consultez le site de documentation de Clang.

Par conception, HWASan ne dispose pas des zones rouges de taille limitée d'ASAN pour détecter les débordements ni de la mise en quarantaine à capacité limitée d'ASAN pour détecter l'utilisation après libération. Pour cette raison, HWASan peut détecter un bug, quelle que soit la taille du débordement ou la durée de désallocation de la mémoire. HWASan présente ainsi un avantage considérable sur ASan.

Toutefois, HWASan dispose d'un nombre limité de valeurs de balise possibles (256), ce qui signifie qu'il existe une probabilité de 0,4% de ne pas détecter un bug lors d'une exécution du programme.

Conditions requises

Les versions récentes (4.14 et ultérieures) du kernel Android commun sont compatibles avec HWAsan dès leur sortie de boîte. Les branches spécifiques à Android 10 ne sont pas compatibles avec HWASan.

La prise en charge de HWASan dans l'espace utilisateur est disponible à partir d'Android 11.

Si vous utilisez un autre noyau, HWASan exige que le noyau Linux accepte les pointeurs tagués dans les arguments d'appel système. Cette fonctionnalité a été implémentée dans les correctifs en amont suivants:

Si vous effectuez une compilation avec une chaîne d'outils personnalisée, assurez-vous qu'elle inclut tout jusqu'au commit LLVM c336557f.

Utiliser HWASan

Utilisez les commandes suivantes pour compiler l'ensemble de la plate-forme à l'aide de HWASan :

lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j

Pour plus de commodité, vous pouvez ajouter le paramètre SANITIZE_TARGET à une définition de produit, comme pour aosp_coral_hwasan.

Pour les utilisateurs qui connaissent AddressSanitizer, la complexité de la compilation est beaucoup moins importante:

  • Inutile d'exécuter la commande "make" deux fois.
  • Les builds incrémentiels fonctionnent dès le départ.
  • Il n'est pas nécessaire de flasher les données utilisateur.

Certaines restrictions AddressSanitizer ont également été supprimées:

  • Les exécutables statiques sont acceptés.
  • Vous pouvez ignorer la désinfection de toute cible autre que libc. Contrairement à ASan, il n'est pas obligatoire qu'une bibliothèque soit nettoyée si tous les exécutables qui l'associent doivent l'être également.

Vous pouvez passer librement d'images HWASan à des images standards avec le même numéro de build (ou supérieur). Il n'est pas nécessaire d'effacer les données de l'appareil.

Pour ignorer le nettoyage d'un module, utilisez LOCAL_NOSANITIZE := hwaddress (Android.mk) ou sanitize: { hwaddress: false } (Android.bp).

Nettoyer des cibles individuelles

HWASan peut être activé par cible dans une compilation régulière (non nettoyée), à condition que libc.so soit également nettoyé. Ajoutez hwaddress: true au bloc "snitize" dans "libc_defaults" dans bionic/libc/Android.bp. Procédez de la même manière dans la cible sur laquelle vous travaillez.

Notez que la désinfection de libc permet de taguer les allocations de mémoire de tas à l'échelle du système, ainsi que de vérifier les tags pour les opérations de mémoire dans libc.so. Cela peut détecter des bugs même dans les binaires pour lesquels HWASan n'était pas activé si l'accès à la mémoire incorrect se trouve dans libc.so (par exemple, pthread_mutex_unlock() sur un mutex édité par delete()).

Il n'est pas nécessaire de modifier les fichiers de compilation si l'ensemble de la plate-forme est compilé à l'aide de HWASan.

Flashstation

À des fins de développement, vous pouvez flasher un build d'AOSP compatible avec HWASan sur un appareil Pixel avec un bootloader déverrouillé à l'aide de Flashstation. Sélectionnez la cible _hwasan, par exemple aosp_flame_hwasan-userdebug. Pour en savoir plus, consultez la documentation du NDK sur HWASan pour les développeurs d'applications.

Améliorer les traces de la pile

HWASan utilise un dérouleur rapide basé sur un pointeur de frame pour enregistrer une trace de pile pour chaque événement d'allocation et de désallocation de mémoire dans le programme. Android active les pointeurs de frame dans le code AArch64 par défaut. Cela fonctionne donc très bien en pratique. Si vous devez dérouler le code géré, définissez HWASAN_OPTIONS=fast_unwind_on_malloc=0 dans l'environnement de processus. Notez que les traces de pile d'accès à la mémoire incorrectes utilisent le dérouleur "lent" par défaut. Ce paramètre n'affecte que les traces d'allocation et de désallocation. Cette option peut être très gourmande en CPU, en fonction de la charge.

Symbolisation

Consultez la section Symbolisation dans "Comprendre les rapports HWASan".

HWASan dans les applications

Comme pour AddressSanitizer, HWASan ne peut pas voir dans le code Java, mais il peut détecter les bugs dans les bibliothèques JNI. Jusqu'à Android 14, l'exécution d'applications HWASan sur un appareil autre que HWASan n'était pas prise en charge.

Sur un appareil HWASan, les applications peuvent être vérifiées avec HWASan en compilant leur code avec SANITIZE_TARGET:=hwaddress dans Make ou -fsanitize=hwaddress dans les indicateurs du compilateur. Sur un appareil non HWASan (exécutant Android 14 ou version ultérieure), un paramètre de fichier wrap.sh LD_HWASAN=1 doit être ajouté. Pour en savoir plus, consultez la documentation pour les développeurs d'applications.