UndefinedBehaviorSanitizer (UBSan) effectue une instrumentation au moment de la compilation pour vérifier divers types de comportement indéfini. Alors qu'UBSan est capable de détecter de nombreux bugs de comportement indéfinis , Android prend en charge :
- alignement
- bourdonner
- bornes
- énumération
- float-cast-overflow
- flotter-diviser-par-zéro
- nombre entier divisé par zéro
- attribut non nul
- nul
- retour
- retourne-attribut-non-null
- base de décalage
- exposant de décalage
- débordement d'entier signé
- inaccessible
- débordement d'entier non signé
- vla lié
unsigned-integer-overflow, bien qu'il ne s'agisse pas d'un comportement techniquement indéfini, est inclus dans le désinfectant et utilisé dans de nombreux modules Android, y compris les composants du serveur multimédia, pour éliminer toute vulnérabilité latente de débordement d'entier.
Mise en œuvre
Dans le système de construction Android, vous pouvez activer UBSan globalement ou localement. Pour activer UBSan globalement, définissez SANITIZE_TARGET dans Android.mk. Pour activer UBSan au niveau de chaque module, définissez LOCAL_SANITIZE et spécifiez les comportements non définis que vous souhaitez rechercher dans Android.mk. Par exemple:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS := -std=c11 -Wall -Werror -O0 LOCAL_SRC_FILES:= sanitizer-status.c LOCAL_MODULE:= sanitizer-status LOCAL_SANITIZE := alignment bounds null unreachable integer LOCAL_SANITIZE_DIAG := alignment bounds null unreachable integer include $(BUILD_EXECUTABLE)
Et la configuration blueprint équivalente (Android.bp) :
cc_binary { cflags: [ "-std=c11", "-Wall", "-Werror", "-O0", ], srcs: ["sanitizer-status.c"], name: "sanitizer-status", sanitize: { misc_undefined: [ "alignment", "bounds", "null", "unreachable", "integer", ], diag: { misc_undefined: [ "alignment", "bounds", "null", "unreachable", "integer", ], }, }, }
Raccourcis UBSan
Android dispose également de deux raccourcis, integer
et default-ub
, pour activer un ensemble de désinfectants en même temps. entier active integer-divide-by-zero
, signed-integer-overflow
et unsigned-integer-overflow
. default-ub
active les vérifications qui ont des problèmes de performances minimes du compilateur bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and vla-bound
. La classe de désinfectant entier peut être utilisée avec SANITIZE_TARGET et LOCAL_SANITIZE, tandis que default-ub ne peut être utilisé qu'avec SANITIZE_TARGET.
Meilleur rapport d'erreur
L'implémentation UBSan par défaut d'Android appelle une fonction spécifiée lorsqu'un comportement indéfini est rencontré. Par défaut, cette fonction est abandonnée. Cependant, à partir d'octobre 2016, UBSan sur Android dispose d'une bibliothèque d'exécution facultative qui fournit des rapports d'erreur plus détaillés, y compris le type de comportement indéfini rencontré, les informations sur le fichier et la ligne de code source. Pour activer ce rapport d'erreur avec des vérifications d'entiers, ajoutez ce qui suit à un fichier Android.mk :
LOCAL_SANITIZE:=integer LOCAL_SANITIZE_DIAG:=integer
La valeur LOCAL_SANITIZE active le nettoyeur pendant la construction. LOCAL_SANITIZE_DIAG active le mode de diagnostic pour le désinfectant spécifié. Il est possible de définir LOCAL_SANITIZE et LOCAL_SANITIZE_DIAG sur des valeurs différentes, mais seules les vérifications dans LOCAL_SANITIZE sont activées. Si une vérification n'est pas spécifiée dans LOCAL_SANITIZE, mais est spécifiée dans LOCAL_SANITIZE_DIAG, la vérification n'est pas activée et les messages de diagnostic ne sont pas donnés.
Voici un exemple des informations fournies par la bibliothèque d'exécution UBSan :
pixel-xl:/ # sanitizer-status ubsan sanitizer-status/sanitizer-status.c:53:6: runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'size_t' (aka 'unsigned long')
Nettoyage de débordement d'entiers
Les débordements d'entiers involontaires peuvent entraîner une corruption de la mémoire ou des vulnérabilités de divulgation d'informations dans les variables associées aux accès à la mémoire ou aux allocations de mémoire. Pour lutter contre cela, nous avons ajouté les désinfectants de débordement d'entiers signés et non signés UndefinedBehaviorSanitizer (UBSan) de Clang pour renforcer le cadre multimédia dans Android 7.0. Dans Android 9, nous avons étendu UBSan pour couvrir davantage de composants et amélioré la prise en charge du système de construction pour celui-ci.
Ceci est conçu pour ajouter des vérifications autour des opérations / instructions arithmétiques - qui pourraient déborder - pour abandonner en toute sécurité un processus si un débordement se produit. Ces désinfectants peuvent atténuer une classe entière de vulnérabilités de corruption de mémoire et de divulgation d'informations dont la cause principale est un dépassement d'entier, comme la vulnérabilité Stagefright d'origine.
Exemples et source
Integer Overflow Sanitization (IntSan) est fourni par le compilateur et ajoute une instrumentation dans le binaire pendant la compilation pour détecter les débordements arithmétiques. Il est activé par défaut dans divers composants de la plate-forme, par exemple /platform/external/libnl/Android.bp
.
Mise en œuvre
IntSan utilise les désinfectants de débordement d'entiers signés et non signés d'UBSan. Cette atténuation est activée au niveau de chaque module. Il permet de sécuriser les composants critiques d'Android et ne doit pas être désactivé.
Nous vous encourageons fortement à activer Integer Overflow Sanitization pour des composants supplémentaires. Les candidats idéaux sont le code natif privilégié ou le code natif qui analyse les entrées utilisateur non fiables. Il y a une petite surcharge de performances associée au désinfectant qui dépend de l'utilisation du code et de la prévalence des opérations arithmétiques. Attendez-vous à un petit pourcentage de frais généraux et testez si les performances sont un problème.
Prise en charge d'IntSan dans les makefiles
Pour activer IntSan dans un makefile, ajoutez :
LOCAL_SANITIZE := integer_overflow # Optional features LOCAL_SANITIZE_DIAG := integer_overflow LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
-
LOCAL_SANITIZE
prend une liste de désinfectants séparés par des virgules,integer_overflow
étant un ensemble pré-emballé d'options pour les désinfectants de débordement d'entiers signés et non signés individuels avec une BLOCKLIST par défaut . -
LOCAL_SANITIZE_DIAG
active le mode de diagnostic pour les désinfectants. Utilisez le mode de diagnostic uniquement pendant les tests, car cela n'abandonnera pas en cas de débordement, ce qui annulera complètement l'avantage de sécurité de l'atténuation. Voir Dépannage pour plus de détails. -
LOCAL_SANITIZE_BLOCKLIST
vous permet de spécifier un fichier BLOCKLIST pour empêcher le nettoyage des fonctions et des fichiers source. Voir Dépannage pour plus de détails.
Si vous souhaitez un contrôle plus précis, activez les désinfectants individuellement à l'aide d'un indicateur ou des deux :
LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow
Prise en charge d'IntSan dans les fichiers Blueprint
Pour activer la désinfection par débordement d'entiers dans un fichier Blueprint, tel que /platform/external/libnl/Android.bp
, ajoutez :
sanitize: { integer_overflow: true, diag: { integer_overflow: true, }, BLOCKLIST: "modulename_BLOCKLIST.txt", },
Comme pour les fichiers make, la propriété integer_overflow
est un ensemble d'options pré-packagées pour les désinfectants de débordement d'entiers signés et non signés individuels avec une BLOCKLIST par défaut .
L'ensemble de propriétés diag
active le mode de diagnostic pour les désinfectants. Utilisez le mode de diagnostic uniquement pendant les tests. Le mode Diagnostics n'abandonne pas en cas de débordement, ce qui annule complètement l'avantage de sécurité de l'atténuation dans les builds utilisateur. Voir Dépannage pour plus de détails.
La propriété BLOCKLIST
permet de spécifier un fichier BLOCKLIST qui permet aux développeurs d'empêcher le nettoyage des fonctions et des fichiers source. Voir Dépannage pour plus de détails.
Pour activer les désinfectants individuellement, utilisez :
sanitize: { misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"], diag: { misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow",], }, BLOCKLIST: "modulename_BLOCKLIST.txt", },
Dépannage
Si vous activez la désinfection par débordement d'entiers dans de nouveaux composants, ou si vous comptez sur des bibliothèques de plate-forme qui ont eu une désinfection par débordement d'entiers, vous pouvez rencontrer quelques problèmes avec des débordements d'entiers bénins provoquant des abandons. Vous devez tester les composants avec la désinfection activée pour vous assurer que les débordements bénins peuvent être détectés.
Pour trouver les abandons causés par le nettoyage dans les builds utilisateur, recherchez les plantages SIGABRT
avec des messages d'abandon indiquant un débordement détecté par UBSan, tels que :
pid: ###, tid: ###, name: Binder:### >>> /system/bin/surfaceflinger <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: sub-overflow'
La trace de la pile doit inclure la fonction provoquant l'abandon, cependant, les débordements qui se produisent dans les fonctions en ligne peuvent ne pas être évidents dans la trace de la pile.
Pour déterminer plus facilement la cause première, activez les diagnostics dans la bibliothèque déclenchant l'abandon et essayez de reproduire l'erreur. Avec les diagnostics activés, le processus ne s'arrêtera pas et continuera à s'exécuter. Ne pas abandonner permet de maximiser le nombre de débordements bénins dans un chemin d'exécution particulier sans avoir à recompiler après avoir corrigé chaque bogue. Les diagnostics génèrent un message d'erreur qui inclut le numéro de ligne et le fichier source à l'origine de l'abandon :
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')
Une fois l'opération arithmétique problématique localisée, assurez-vous que le débordement est bénin et intentionnel (par exemple, n'a pas d'incidence sur la sécurité). Vous pouvez résoudre l'abandon du désinfectant en :
- Refactoring du code pour éviter le débordement ( exemple )
- Débordement explicite via les fonctions __builtin_*_overflow de Clang ( exemple )
- Désactivation de la désinfection dans la fonction en spécifiant l'attribut
no_sanitize
( exemple ) - Désactivation du nettoyage d'une fonction ou d'un fichier source via un fichier BLOCKLIST ( exemple )
Vous devez utiliser la solution la plus granulaire possible. Par exemple, une grande fonction avec de nombreuses opérations arithmétiques et une seule opération de débordement devrait avoir l'opération unique refactorisée plutôt que la fonction entière en BLOCKLIST.
Les schémas courants pouvant entraîner des débordements bénins incluent :
- Conversions implicites où un débordement non signé se produit avant d'être converti en un type signé ( exemple )
- Suppressions de liste chaînée qui décrémente l'index de boucle lors de la suppression ( exemple )
- Affectation d'un type non signé à -1 au lieu de spécifier la valeur maximale réelle ( exemple )
- Boucles qui décrémentent un entier non signé dans la condition ( exemple , exemple )
Il est recommandé aux développeurs de s'assurer que les cas où l'assainisseur détecte un débordement qu'il est bien bénin, sans effets secondaires imprévus ni implications pour la sécurité avant de désactiver l'assainissement.
Désactiver IntSan
Vous pouvez désactiver IntSan avec des BLOCKLISTS ou des attributs de fonction. Désactiver avec parcimonie et uniquement lorsque la refactorisation du code est autrement déraisonnable ou s'il y a une surcharge de performances problématique.
Consultez la documentation Clang en amont pour plus d'informations sur la désactivation d'IntSan avec les attributs de fonction et le formatage du fichier BLOCKLIST . BLOCKLISTing doit être limité au désinfectant particulier en utilisant des noms de section spécifiant le désinfectant cible pour éviter d'avoir un impact sur d'autres désinfectants.
Validation
Actuellement, il n'y a pas de test CTS spécifiquement pour Integer Overflow Sanitization. Au lieu de cela, assurez-vous que les tests CTS réussissent avec ou sans IntSan activé pour vérifier qu'il n'a pas d'impact sur l'appareil.
Assainissement des limites
BoundsSanitizer (BoundSan) ajoute une instrumentation aux fichiers binaires pour insérer des contrôles de limites autour des accès aux tableaux. Ces vérifications sont ajoutées si le compilateur ne peut pas prouver au moment de la compilation que l'accès sera sûr et si la taille du tableau sera connue au moment de l'exécution, afin qu'elle puisse être vérifiée. Android 10 déploie BoundSan en Bluetooth et codecs. BoundSan est fourni par le compilateur et est activé par défaut dans divers composants de la plate-forme.
Mise en œuvre
BoundSan utilise le désinfectant de limites d'UBSan . Cette atténuation est activée au niveau de chaque module. Il permet de sécuriser les composants critiques d'Android et ne doit pas être désactivé.
Nous vous encourageons fortement à activer BoundSan pour des composants supplémentaires. Les candidats idéaux sont le code natif privilégié ou le code natif complexe qui analyse les entrées utilisateur non fiables. La surcharge de performances associée à l'activation de BoundSan dépend du nombre d'accès à la baie dont la sécurité ne peut pas être prouvée. Attendez-vous à un petit pourcentage de frais généraux en moyenne et testez si les performances sont un problème.
Activation de BoundSan dans les fichiers Blueprint
BoundSan peut être activé dans les fichiers Blueprint en ajoutant "bounds"
à la propriété misc_undefined
sanitize pour les modules binaires et de bibliothèque :
sanitize: { misc_undefined: ["bounds"], diag: { misc_undefined: ["bounds"], }, BLOCKLIST: "modulename_BLOCKLIST.txt",
diagnostic
La propriété diag
active le mode de diagnostic pour les désinfectants. Utilisez le mode de diagnostic uniquement pendant les tests. Le mode Diagnostics n'abandonne pas en cas de débordement, ce qui annule l'avantage de sécurité de l'atténuation et entraîne une surcharge de performances plus élevée, il n'est donc pas recommandé pour les versions de production.
LISTE DE BLOCAGE
La propriété BLOCKLIST
permet la spécification d'un fichier BLOCKLIST que les développeurs peuvent utiliser pour empêcher le nettoyage des fonctions et des fichiers source. Utilisez cette propriété uniquement si les performances sont un problème et que les fichiers/fonctions ciblés y contribuent de manière substantielle. Auditez manuellement ces fichiers/fonctions pour vous assurer que les accès à la baie sont sécurisés. Voir Dépannage pour plus de détails.
Activer BoundSan dans les makefiles
BoundSan peut être activé dans les makefiles en ajoutant "bounds"
à la variable LOCAL_SANITIZE
pour les modules binaires et de bibliothèque :
LOCAL_SANITIZE := bounds # Optional features LOCAL_SANITIZE_DIAG := bounds LOCAL_SANITIZE_BLOCKLIST := modulename_BLOCKLIST.txt
LOCAL_SANITIZE
accepte une liste de désinfectants séparés par une virgule.
LOCAL_SANITIZE_DIAG
active le mode de diagnostic. Utilisez le mode de diagnostic uniquement pendant les tests. Le mode Diagnostics n'abandonne pas en cas de débordement, ce qui annule l'avantage de sécurité de l'atténuation et entraîne une surcharge de performances plus élevée, il n'est donc pas recommandé pour les versions de production.
LOCAL_SANITIZE_BLOCKLIST
permet de spécifier un fichier BLOCKLIST qui permet aux développeurs d'empêcher le nettoyage des fonctions et des fichiers source. Utilisez cette propriété uniquement si les performances sont un problème et que les fichiers/fonctions ciblés y contribuent de manière substantielle. Auditez manuellement ces fichiers/fonctions pour vous assurer que les accès à la baie sont sécurisés. Voir Dépannage pour plus de détails.
Désactivation de BoundSan
Vous pouvez désactiver BoundSan dans les fonctions et les fichiers source avec des BLOCKLISTS ou des attributs de fonction. Il est préférable de garder BoundSan activé, donc ne le désactivez que si la fonction ou le fichier crée une surcharge de performances importante et que la source a été examinée manuellement.
Pour plus d'informations sur la désactivation de BoundSan avec les attributs de fonction et le formatage du fichier BLOCKLIST , reportez-vous à la documentation Clang LLVM. Étendez la BLOCKLISTing au désinfectant particulier en utilisant des noms de section spécifiant le désinfectant cible pour éviter d'avoir un impact sur d'autres désinfectants.
Validation
Il n'y a pas de test CTS spécifiquement pour BoundSan. Au lieu de cela, assurez-vous que les tests CTS réussissent avec ou sans BoundSan activé pour vérifier qu'il n'affecte pas l'appareil.
Dépannage
Testez soigneusement les composants après avoir activé BoundSan pour vous assurer que tous les accès hors limites non détectés précédemment sont traités.
Les erreurs BoundSan peuvent être facilement identifiées car elles incluent le message d'abandon suivant :
pid: ###, tid: ###, name: Binder:### >>> /system/bin/foobar <<< signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr -------- Abort message: 'ubsan: out-of-bounds'
Lors de l'exécution en mode diagnostics, le fichier source, le numéro de ligne et la valeur d'index sont imprimés dans logcat
. Par défaut, ce mode ne génère pas de message d'abandon. Passez en revue logcat
pour rechercher d'éventuelles erreurs.
external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'