UndefinedBehaviorSanitizer

UndefinedBehaviorSanitizer (UBSan) effectue une instrumentation au moment de la compilation pour vérifier les différents types de comportements non définis. Bien qu'UBSan puisse détection beaucoup bugs de comportement non définis, Android est compatible avec:

  • alignement
  • Booléen
  • limites
  • enum
  • float-cast-overflow
  • division-flottante-par-zéro
  • division-par-zéro par nombre entier
  • attribut non nul
  • null
  • retour
  • return-nonnull-attribute
  • base-maj
  • exposant-décalage
  • Débordement d'entiers signés
  • injoignable
  • Dépassement d'entiers non signé
  • lié à vla

unsigned-integer-overflow, sans être techniquement défini est inclus dans le désinfectant et utilisé dans de nombreux modules Android, y compris les composants Mediaserver, afin d'éliminer tout dépassement d'entiers latents les failles.

Implémentation

Dans le système de compilation Android, vous pouvez activer UBSan globalement ou localement. Pour activer UBSan à l'échelle mondiale, définissez SANITIZE_TARGET dans Android.mk. Pour activer UBSan en fonction par module, définissez LOCAL_SANITIZE et spécifiez les comportements non définis qui que vous voulez rechercher dans Android.mk. 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)

Configuration du plan é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. Nombre entier active integer-divide-by-zero, signed-integer-overflow et unsigned-integer-overflow. default-ub active les vérifications avec un compilateur minimal problèmes de performances: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable and vla-bound. La la classe de désinfection "Entier" peut être utilisée avec SANITIZE_TARGET et LOCAL_SANITIZE, alors que default-ub ne peut être utilisé qu'avec SANITIZE_TARGET.

Amélioration des rapports d'erreurs

L'implémentation UBSan par défaut d'Android appelle une fonction spécifiée lorsque un comportement non défini. Par défaut, cette fonction est abandonnée. Toutefois, depuis octobre 2016, UBSan sur Android dispose d'une bibliothèque d'exécution facultative Permet de créer des rapports d'erreurs plus détaillés, y compris concernant les types de comportements non définis des informations sur les fichiers et la ligne de code source. Pour activer cette erreur La création de rapports avec des vérifications d'entiers ajoute ce qui suit à un fichier Android.mk:

LOCAL_SANITIZE:=integer
LOCAL_SANITIZE_DIAG:=integer

La valeur LOCAL_SANITIZE active le nettoyage pendant la compilation. LOCAL_SANITIZE_DIAG active le mode diagnostic pour le désinfection spécifié. Il est possible de définir LOCAL_SANITIZE et LOCAL_SANITIZE_DIAG sur des valeurs différentes, mais seules ces vérifications dans LOCAL_SANITIZE sont activées. Si aucune vérification n'est spécifiée dans LOCAL_SANITIZE, mais spécifié dans LOCAL_SANITIZE_DIAG, le test n’est pas activé et aucun message de diagnostic ne s'affiche.

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 des dépassements d'entiers

Les dépassements d'entiers inattendus peuvent entraîner une corruption de la mémoire ou des informations les failles dans les variables associées aux accès à la mémoire ou allocations de mémoire allouées. Pour lutter contre ce problème, nous avons ajouté UndefinedBehaviorSanitizer (UBSan) signés et non signés et non signés pour les désinfections de dépassement d'entiers renforcer le framework multimédia d'Android 7.0. Sous Android 9, développé UBSan pour couvrir davantage de composants et améliorer sa compatibilité avec le système de compilation.

Elle permet d'ajouter des vérifications liées aux calculs arithmétiques d'instructions et d'opérations, qui pourraient Débordement : pour annuler un processus en toute sécurité en cas de débordement. Ces outils de nettoyage peuvent atténuer la corruption d'une classe entière de mémoire et les failles de divulgation d'informations, où l'origine du problème est un nombre entier comme la faille Stagefright d'origine.

Exemples et source

Integer Overflow Sanitization (IntSan) est fourni par le compilateur et ajoute une instrumentation dans le binaire lors de la compilation pour détecter des opérations arithmétiques déborde. Elle est activée par défaut dans différents composants du plate-forme, par exemple /platform/external/libnl/Android.bp

Implémentation

IntSan utilise les désinfections de dépassement d'entiers signés et non signés d'UBSan. Ce l'atténuation est activée au niveau du module. Cela permet de garder les composants critiques d'Android et ne doit pas être désactivé.

Nous vous encourageons vivement à activer la suppression du dépassement d'entiers pour obtenir composants. Les candidats idéaux sont du code natif privilégié ou du code natif qui analyse les entrées utilisateur non fiables. L'impact sur les performances est faible avec le désinfectant qui dépend de l'utilisation du code et de la prévalence les opérations arithmétiques. Attendez-vous à un petit pourcentage de frais généraux et vérifiez si les performances sont préoccupantes.

Prise en charge d'IntSan dans les fichiers makefile

Pour activer IntSan dans un fichier 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 une virgule, integer_overflow étant un ensemble d'options prêtes à l'emploi pour les désinfectants individuels signés et non signés pour dépassement de dépassement d'entiers avec un par défaut LISTE DE BLOQUER.
  • LOCAL_SANITIZE_DIAG active le mode diagnostic pour le désinfectants. Le mode Diagnostic n'est utilisé que pendant les tests, en cas de dépassement, annulant complètement l'avantage de sécurité l'atténuation des risques. Consultez la section Dépannage. pour en savoir plus.
  • LOCAL_SANITIZE_BLOCKLIST vous permet de spécifier une LISTE DE BLOQUER pour éviter que les fonctions et les fichiers sources ne soient nettoyés. Voir Consultez la section de dépannage pour en savoir plus plus de détails.

Si vous voulez un contrôle plus précis, activez les désinfectants individuellement à l'aide d'un ou les deux:

LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow
    LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow

Assurer la compatibilité avec IntSan dans les fichiers de plan

Pour activer le nettoyage des dépassements de nombre d'entiers dans un fichier de plan, tel que /platform/external/libnl/Android.bp, ajouter:

   sanitize: {
          integer_overflow: true,
          diag: {
              integer_overflow: true,
          },
          BLOCKLIST: "modulename_BLOCKLIST.txt",
       },

Comme pour les fichiers "make", la propriété integer_overflow est un package ensemble d'options pour le débordement d'entiers signés et non signés individuels désinfectants avec une valeur par défaut LISTE DE BLOQUER.

L'ensemble de propriétés diag active le mode diagnostic pour désinfectants. Utilisez le mode Diagnostic uniquement pendant les tests. Le mode Diagnostic ne en cas de dépassement, ce qui annule complètement l'avantage de sécurité atténuation dans les builds utilisateur. Pour en savoir plus, consultez la section Dépannage.

La propriété BLOCKLIST permet de spécifier un fichier BLOCKLIST. qui permet aux développeurs d'empêcher que les fonctions et les fichiers sources désinfectées. Consultez la section Dépannage pour pour en savoir plus.

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 le nettoyage des dépassements d'entiers dans de nouveaux composants ou si vous utilisez de plate-forme dont le nettoyage par dépassement d'entiers est appliqué, vous pouvez rencontrer quelques problèmes de dépassements d'entiers inoffensifs entraînant des abandons. Vous devez tester composants dont le nettoyage est activé pour que les dépassements inoffensifs puissent être mis en évidence.

Pour trouver les abandons causés par le nettoyage des builds utilisateur, recherchez SIGABRT plante avec des messages d'annulation indiquant qu'un débordement a été détecté par UBSan, par exemple:

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 à l'origine de l'annulation. Les dépassements qui se produisent dans les fonctions intégrées peuvent ne pas être évidents dans la trace de la pile.

Pour déterminer plus facilement l'origine du problème, activez les diagnostics dans la bibliothèque déclenche l'abandon et tente de reproduire l'erreur. Avec sont activés, le processus n'annule pas continuent de s'exécuter. Ne pas abandonner permet de maximiser le nombre de dépassements anodins dans une chemin d'exécution particulier sans avoir à recompiler après avoir corrigé chaque bug. Les diagnostics génèrent un message d'erreur incluant le numéro de ligne et la source à l'origine de l'annulation:

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 détectée, assurez-vous que le débordement est inoffensif et intentionnel (elle n'a aucune incidence sur la sécurité, par exemple). Vous pouvez traiter les avorter par:

  • Refactoriser le code pour éviter le débordement (exemple)
  • Débordement explicite via la commande __builtin_*_overflow de Clang Fonctions (exemple)
  • Désactiver le nettoyage dans la fonction en spécifiant l'attribut no_sanitize (exemple)
  • Désactiver le nettoyage d'une fonction ou d'un fichier source via un fichier BLOCKLIST (exemple)

Vous devez utiliser la solution la plus précise possible. Par exemple, un grand fonction comportant de nombreuses opérations arithmétiques et une seule opération de débordement doit être refactorisée pour une seule opération plutôt que pour la fonction entière ; SUR LISTE DE BLOQUER.

Les modèles courants pouvant entraîner des dépassements anodins incluent:

  • Implicite Diffusions où un débordement non signé se produit avant d'être converti en type signé (exemple)
  • Suppressions de listes associées qui décrémentent l'index de boucle lors de la suppression (exemple)
  • Attribuer 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ù le désinfectant détecte un débordement qu'il est en effet inoffensif, sans effets secondaires ni sécurité avant de désactiver le nettoyage.

Désactiver IntSan

Vous pouvez désactiver IntSan à l'aide de LISTES DE BLOQUER ou d'attributs de fonction. Désactiver avec parcimonie et seulement lors de la refactorisation, le code est autrement déraisonnable ou s'il y a des problèmes de performances.

Pour en savoir plus sur la désactivation d'IntSan, consultez la documentation Clang en amont. avec la fonction attributs et le fichier BLOCKLIST mise en forme. La LISTE DE BLOQUER doit être limitée au désinfectant en question en utilisant des noms de section spécifiant le désinfectant cible pour éviter d'affecter les autres désinfectants.

Validation

À l'heure actuelle, il n'existe pas de test CTS spécifique à la suppression du débordement d'entiers. Assurez-vous plutôt que les tests CTS réussissent avec ou sans IntSan activé pour vérifier que cela n’affecte pas l’appareil.

Assainissement des limites

BoundsSanitizer (BoundSan) ajoute une instrumentation aux binaires pour insérer des limites et vérifie les accès au tableau. Ces vérifications sont ajoutées si le compilateur ne peut pas prouver, au moment de la compilation, que l'accès est sécurisé et que la taille du tableau seront connus au moment de l'exécution, afin de pouvoir être comparés. Android 10 déploie BoundSan dans Bluetooth et les codecs. BoundSan est fourni par le compilateur et est activé par dans divers composants de la plate-forme.

Implémentation

BoundSan utilise l'API UBSan gel désinfectant. Cette atténuation est activée au niveau des modules. Cela vous aide assurer la sécurité des composants essentiels d'Android et ne doivent pas être désactivés.

Nous vous encourageons vivement à activer BoundSan pour des composants supplémentaires. Les candidats idéaux sont du code natif privilégié ou du code natif complexe qui analyse des entrées utilisateur non fiables. L'impact sur les performances associé à l'activation de BoundSan dépend du nombre d'accès aux tableaux dont la sécurité n'a pas pu être prouvée. Attendez-vous à un faible pourcentage d'impact en moyenne et tester les performances.

Activer BoundSan dans les fichiers de plan

Vous pouvez activer BoundSan dans les fichiers de plan en ajoutant "bounds" à la propriété misc_undefined "snitize" pour le binaire et la bibliothèque modules:

    sanitize: {
       misc_undefined: ["bounds"],
       diag: {
          misc_undefined: ["bounds"],
       },
       BLOCKLIST: "modulename_BLOCKLIST.txt",
diagnostic

La propriété diag active le mode diagnostic pour les désinfectants. Utilisez le mode Diagnostic uniquement pendant les tests. Le mode diagnostic ne procède pas à l'annulation le ce qui annule l'avantage de sécurité sans frais par l'atténuation sur des coûts de performances plus élevés, ce qui n'est donc pas recommandé pour les builds de production.

LISTE DE BLOQUER

La propriété BLOCKLIST permet de spécifier une liste de blocage. que les développeurs peuvent utiliser pour empêcher les fonctions et les fichiers sources d'être désinfectées. N'utilisez cette propriété que si les performances sont un problème et si les les fichiers/fonctions contribuent de manière significative. Auditer manuellement ces fichiers/fonctions pour garantir la sécurité des accès aux tableaux. Consultez la section Dépannage pour en savoir plus plus de détails.

Activer BoundSan dans les fichiers makefile

Vous pouvez activer BoundSan dans les fichiers makefile 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 diagnostic. Utiliser les diagnostics pendant les tests. Le mode diagnostic ne s'annule pas en cas de dépassement, ce qui annule l'avantage de sécurité sans frais par l'atténuation sur les performances. Elle n'est donc pas recommandée pour les builds de production.

LOCAL_SANITIZE_BLOCKLIST permet de spécifier une LISTE DE BLOQUER qui permet aux développeurs d'empêcher que les fonctions et les fichiers sources désinfectées. N'utilisez cette propriété que si les performances sont un problème et si les les fichiers/fonctions contribuent de manière significative. Auditer manuellement ces fichiers/fonctions pour garantir la sécurité des accès aux tableaux. Consultez la section Dépannage pour en savoir plus plus de détails.

Désactiver BoundSan

Vous pouvez désactiver BoundSan dans les fonctions et les fichiers sources à l'aide de listes de blocage ou . Il est préférable de laisser BoundSan activé. Ne le désactivez donc la fonction ou le fichier entraîne une surcharge de performances importante, la source a été examinée manuellement.

Pour en savoir plus sur la désactivation de BoundSan avec function attributs et le fichier BLOCKLIST , consultez la documentation sur Clang LLVM. Définissez le champ d'application ajouter à la LISTE DE BLOQUER le désinfectant en utilisant des noms de section spécifiant le cibler du désinfectant pour éviter d'avoir un impact sur les autres désinfectants.

Validation

Il n'existe pas de test CTS spécifique à BoundSan. Assurez-vous plutôt que CTS réussissent les tests avec ou sans BoundSan activé pour vérifier que cela n'affecte pas l'appareil.

Dépannage

Testez minutieusement les composants après avoir activé BoundSan pour vous assurer que tous les composants les accès hors limites non détectés sont traités.

Les erreurs BoundSan sont faciles à identifier, car elles incluent les éléments suivants : Message d'abandon tombstone:

    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 Diagnostic, le fichier source, le numéro de ligne et l'index sont affichées sur logcat. Par défaut, ce mode générer un message d'abandon. Examinez logcat pour vérifier si des les erreurs.

    external/foo/bar.c:293:13: runtime error: index -1 out of bounds for type 'int [24]'