Mémoire d'exécution uniquement (XOM) pour les binaires AArch64

<ph type="x-smartling-placeholder">

Par défaut, les sections de code exécutables pour les binaires système AArch64 sont marquées exécution uniquement (non lisible) pour renforcer la protection par rapport au code juste-à-temps par réutilisation. Du code qui combine des données et du code, et du code qui a été conçu inspecte ces sections (sans remapper au préalable les segments de mémoire comme lisibles) ; ne fonctionnent plus. Applications avec un SDK cible de 10 (niveau d'API 29 ou supérieur) sont affectés si l'application tente de lire les sections de code les bibliothèques système compatibles avec la mémoire d'exécution uniquement (XOM) en mémoire en marquant la section comme lisible.

Pour profiter pleinement de cette atténuation, la prise en charge du matériel et du noyau est obligatoire. Sans cela, l'atténuation ne pourrait être appliquée que partiellement. La <ph type="x-smartling-placeholder"></ph> le noyau commun Android 4.9 contient les correctifs appropriés pour fournir la prise en charge sur les appareils ARMv8.2.

Implémentation

Les binaires AArch64 générés par le compilateur supposent que le code et les données ne sont pas se mélangent. L'activation de cette fonctionnalité n'a pas d'incidence négative sur les performances des l'appareil.

Pour le code qui doit effectuer une introspection intentionnelle de la mémoire sur ses segments exécutables, nous vous conseillons d'appeler mprotect sur la segments de code devant être inspectés pour être lisibles, supprimer la lisibilité une fois l'inspection terminée.
Cette implémentation entraîne des lectures dans des segments de mémoire marqués comme l'exécution uniquement pour entraîner une erreur de segmentation (SEGFAULT). Cela peut se produire en raison d'un bogue, d'une vulnérabilité, de données mélangées avec du code (pooling littéral) ou de l'introspection intentionnelle de la mémoire.

Compatibilité et impact des appareils

Appareils dotés d'un matériel antérieur ou de noyaux antérieurs (inférieurs à 4.9) et ne possédant pas les correctifs requis pourraient ne pas prendre entièrement en charge ou bénéficier de cette fonctionnalité. Appareils sans prise en charge du noyau ne peut pas forcer l’accès de l’utilisateur à la mémoire en exécution uniquement, Toutefois, le code du noyau qui vérifie explicitement si une page est lisible peut toujours appliquer cette propriété, comme process_vm_readv().

L'option de noyau CONFIG_ARM64_UAO doit être définie dans le noyau pour assurez-vous que le noyau respecte les pages utilisateur marquées uniquement en exécution. Version antérieure d'ARMv8 ou les appareils ARMv8.2 sur lesquels le paramètre de remplacement de l'accès utilisateur (UAO) est désactivé, en tirent pleinement parti et peuvent toujours lire des pages en exécution uniquement à l'aide les appels système.

Refactoriser le code existant

Le code qui a été transféré à partir d'AArch32 peut contenir des données mélangées et ce qui entraîne des problèmes. Dans de nombreux cas, la résolution de ces problèmes est aussi simple comme le déplacement des constantes vers une section .data du fichier d'assemblage.

Vous devrez peut-être refactoriser l'assemblage manuscrit pour séparer le pooling local. constantes.

Exemples :

Les binaires générés par le compilateur Clang ne devraient pas présenter de problèmes de données sont mélangés dans le code. Si le code généré GNU Compiler Collection (GCC) est (à partir d'une bibliothèque statique), inspectez le binaire de sortie pour de vérifier que les constantes n'ont pas été regroupées dans des sections de code.

Si une introspection de code est nécessaire sur les sections de code exécutables, appelez d'abord mprotect pour marquer le code comme lisible. Ensuite, après l'opération, est terminée, appelez de nouveau mprotect pour la marquer comme illisible.

Activer XOM

L'option "Execute-only" (exécution seule) est activée par défaut pour tous les binaires 64 bits du build. du système d'exploitation.

Désactiver XOM

Vous pouvez désactiver l'exécution uniquement au niveau d'un module, pour l'ensemble d'un sous-répertoire ou pour l'ensemble d'un build.

Vous pouvez désactiver le XOM pour des modules individuels qui ne peuvent pas être refactorisés ou qui doivent lire leurs code exécutable, en définissant LOCAL_XOM et xom sur false.

// Android.mk
LOCAL_XOM := false

// Android.bp
cc_binary { // or other module types
   ...
   xom: false,
}

Si la mémoire réservée à l'exécution est désactivée dans une bibliothèque statique, le système de compilation applique à tous les modules dépendants de cette bibliothèque statique. Vous pouvez remplacer à l'aide de xom: true,.

Pour désactiver la mémoire d'exécution seule dans un sous-répertoire spécifique (par exemple, foo/bar/), transmettez la valeur à XOM_EXCLUDE_PATHS.

make -j XOM_EXCLUDE_PATHS=foo/bar

Vous pouvez également définir PRODUCT_XOM_EXCLUDE_PATHS dans la configuration de votre produit.

Vous pouvez désactiver les binaires d'exécution uniquement de manière globale en transmettant ENABLE_XOM=false à votre commande make.

make -j ENABLE_XOM=false

Validation

Aucun test de validation ou CTS n'est disponible pour l'exécution uniquement mémoire. Vous pouvez vérifier manuellement les binaires à l'aide de readelf et en vérifiant les indicateurs de segment.