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.