Intégrité du flux de contrôle

Depuis 2016, environ 86% de toutes les failles sur Android concernent la sécurité de la mémoire. liés. La plupart des vulnérabilités sont exploitées par des attaquants qui changent la normale de contrôle d'une application pour effectuer des activités malveillantes arbitraires tous les privilèges de l'application exploitée. Flux de contrôle (CFI) est un mécanisme de sécurité qui interdit toute modification graphique de flux de contrôle original d'un binaire compilé, ce qui le rend beaucoup plus difficile pour effectuer de telles attaques.

Dans Android 8.1, nous avons activé l'implémentation de CFI par LLVM dans la pile multimédia. Dans Android 9, nous avons activé CFI dans plus de composants, ainsi que dans le noyau. La CFI du système est activé par défaut, mais vous devez activer le noyau CFI.

CFI de LLVM nécessite de compiler avec Optimisation au moment de la liaison (LTO, LTO). Le LTO conserve la représentation du bitcode LLVM des fichiers d'objet jusqu'à au moment du lien, ce qui permet au compilateur de mieux comprendre les optimisations peut être effectuée. L'activation du LTO réduit la taille du binaire final et améliore mais augmente le temps de compilation. Lors des tests sur Android, la combinaison de LTO et de CFI entraînent une surcharge négligeable sur la taille et les performances du code ; dans un et quelques cas se sont améliorés.

Pour plus de détails techniques sur CFI et sur la façon dont les autres contrôles de contrôle consultez la documentation LLVM sur la conception documentation.

Exemples et source

CFI est fourni par le compilateur et ajoute une instrumentation dans le binaire pendant à la compilation. Nous acceptons CFI dans la chaîne d'outils Clang et le système de compilation Android. dans AOSP.

CFI est activé par défaut pour les appareils Arm64 pour l'ensemble des composants de /platform/build/target/product/cfi-common.mk Il est aussi directement activé dans un ensemble de composants multimédias créer fichiers/plan tels que /platform/frameworks/av/media/libmedia/Android.bp et /platform/frameworks/av/cmds/stagefright/Android.mk.

Implémenter la CFI du système

CFI est activé par défaut si vous utilisez Clang et le système de compilation Android. Étant donné que CFI contribue à protéger les utilisateurs d'Android, vous ne devez pas le désactiver.

D'ailleurs, nous vous encourageons vivement à activer CFI pour les composants supplémentaires. Les candidats idéaux sont le code natif privilégié, ou code natif qui traite des entrées utilisateur non fiables. Si vous utilisez Clang et le système de compilation Android, vous pouvez activer CFI dans de nouveaux composants en ajoutant quelques lignes à vos fichiers makefile ou les fichiers de plan.

Compatibilité avec CFI dans les fichiers makefile

Pour activer CFI dans un fichier Make, tel que /platform/frameworks/av/cmds/stagefright/Android.mk, procédez comme suit : ajouter:

LOCAL_SANITIZE := cfi
# Optional features
LOCAL_SANITIZE_DIAG := cfi
LOCAL_SANITIZE_BLACKLIST := cfi_blacklist.txt

  • LOCAL_SANITIZE spécifie CFI comme désinfectant pendant la créer.
  • LOCAL_SANITIZE_DIAG active le mode diagnostic pour CFI. Le mode diagnostic affiche des informations de débogage supplémentaires dans Logcat pendant ce qui est utile lorsque vous développez et testez vos builds. Marque veillez toutefois à supprimer le mode diagnostic sur les builds de production.
  • LOCAL_SANITIZE_BLACKLIST permet aux composants de sélectionner désactiver l'instrumentation CFI pour des fonctions ou des fichiers sources individuels. Toi utiliser une liste noire en dernier recours pour résoudre les problèmes rencontrés par les utilisateurs pourrait autrement exister. Pour en savoir plus, consultez Désactiver CFI

Prendre en charge CFI dans les fichiers de plan

Pour activer CFI dans un fichier de plan, tel que /platform/frameworks/av/media/libmedia/Android.bp, procédez comme suit : ajouter:

   sanitize: {
        cfi: true,
        diag: {
            cfi: true,
        },
        blacklist: "cfi_blacklist.txt",
    },

Dépannage

Si vous activez CFI dans de nouveaux composants, vous pouvez rencontrer quelques problèmes avec Erreurs de non-concordance du type de fonction et Non-concordance du type de code d'assembly erreurs.

Les erreurs de non-concordance des types de fonction se produisent, car CFI limite les appels indirects uniquement accéder aux fonctions dont le type dynamique est le même que le type statique utilisé dans la . CFI limite les appels de fonction membres virtuels et non virtuels afin de ne faire que sauter aux objets qui sont une classe dérivée du type statique de l'objet utilisé pour passer l'appel. Cela signifie que lorsque votre code ne respecte pas l'un de ces l'instrumentation ajoutée par CFI sera abandonnée. Par exemple, la trace de la pile montre un SIGABRT et Logcat contient une ligne concernant le flux de contrôle l'intégrité de trouver une non-concordance.

Pour résoudre ce problème, assurez-vous que la fonction appelée possède le même type que celui qui était déclaré de manière statique. Voici deux exemples de CL:

Un autre problème possible consiste à essayer d'activer CFI dans du code contenant des données à l'assembly. Comme le code d'assemblage n'est pas typé, le type ne correspondent pas.

Pour résoudre ce problème, créez des wrappers de code natifs pour chaque appel d'assembly et attribuez au encapsule la même signature de fonction que l'indicateur appelant. Le wrapper peut ensuite directement le code d'assemblage. Comme les branches directes ne sont pas instrumentées par CFI (ils ne peuvent pas être repointés au moment de l'exécution et ne présentent donc pas de risque de sécurité) cela résoudra le problème.

S'il y a trop de fonctions d'assemblage et qu'elles ne peuvent pas toutes être corrigées, vous pouvez mettre également sur liste noire toutes les fonctions contenant des appels indirects à l'assembly. C'est non recommandé, car cela désactive les contrôles CFI sur ces fonctions, ce qui ouvre sur votre surface d'attaque.

Désactivation de CFI

Comme nous n'avons observé aucun impact sur les performances, vous ne devriez pas avoir à désactiver CFI. Toutefois, en cas d'impact sur les utilisateurs, vous pouvez désactiver CFI de manière sélective. pour des fonctions ou des fichiers sources individuels en fournissant un fichier de liste noire de nettoyage au moment de la compilation. La liste noire demande au compilateur de désactiver CFI et une instrumentation dans des emplacements spécifiés.

Le système de compilation Android prend en charge les listes noires par composant (ce qui permet de choisir les fichiers sources ou les fonctions individuelles qui ne recevront pas CFI instrumentation) pour Make et Soong. Pour en savoir plus sur le format d'un fichier liste noire, consultez la documentation en amont Documentation Clang

Validation

Il n'existe actuellement aucun test CTS spécifique à CFI. Assurez-vous plutôt que Les tests CTS réussissent avec ou sans CFI activé pour vérifier que CFI n'a aucun impact l'appareil.