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_BLACKLIST := modulename_blacklist.txt
  • LOCAL_SANITIZE prend une liste de désinfectants séparés par des virgules, integer_overflow étant 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 liste noire 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_BLACKLIST vous permet de spécifier un fichier de liste noire 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,
      },
      blacklist: "modulename_blacklist.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 liste noire 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é blacklist permet de spécifier un fichier de liste noire 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",],
      },
      blacklist: "modulename_blacklist.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 de liste noire ( 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 sur liste noire.

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 listes noires 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 des fichiers de la liste noire . La liste noire doit être limitée 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.