Créer une règle SELinux

Cette page explique comment les règles SELinux sont créées. Les règles SELinux sont créées à partir de la combinaison des règles AOSP de base (plate-forme) et des règles spécifiques à l'appareil (fournisseur). Le flux de création des règles SELinux pour Android 4.4 à Android 7.0 fusionnait tous les fragments sepolicy, puis générait des fichiers monolithiques dans le répertoire racine. Cela signifiait que les fournisseurs de SoC et les fabricants d'ODM modifiaient boot.img (pour les appareils non-A/B) ou system.img (pour les appareils A/B) chaque fois que les règles étaient modifiées.

Dans Android 8.0 et versions ultérieures, les règles de plate-forme et de fournisseur sont créées séparément. Les SoC et les OEM peuvent mettre à jour leurs parties des règles, créer leurs images (telles que vendor.img et boot.img), puis mettre à jour ces images indépendamment des mises à jour de la plate-forme.

Toutefois, comme les fichiers de règles SELinux modularisés sont stockés sur les partitions /vendor, le processus init doit installer les partitions system et de fournisseur plus tôt afin de pouvoir lire les fichiers SELinux à partir de ces partitions et les fusionner avec les fichiers SELinux de base dans le répertoire system (avant de les charger dans le noyau).

Fichiers sources

La logique de création de SELinux se trouve dans les fichiers suivants :

  • external/selinux : projet SELinux externe, utilisé pour créer des utilitaires de ligne de commande HOST afin de compiler les règles et les libellés SELinux.
    • external/selinux/libselinux : Android n'utilise qu'un sous-ensemble du projet libselinux externe, ainsi que certaines personnalisations spécifiques à Android. Pour en savoir plus, consultez external/selinux/README.android.
    • external/selinux/libsepol:
      • chkcon: : détermine si un contexte de sécurité est valide pour une règle binaire donnée (exécutable hôte).
      • libsepol : bibliothèque SELinux pour manipuler les règles de sécurité binaires (bibliothèque statique/partagée hôte, bibliothèque statique cible).
    • external/selinux/checkpolicy : compilateur de règles SELinux (exécutables hôtes : checkpolicy, checkmodule, et dispol). Dépend de libsepol.
  • system/sepolicy : configurations de règles SELinux Android de base, y compris les contextes et les fichiers de règles. La logique de création sepolicy principale se trouve également ici (system/sepolicy/Android.mk).

Pour en savoir plus sur les fichiers dans system/sepolicy, consultez Fichiers clés.

Android 7.x et versions antérieures

Cette section explique comment les règles SELinux sont créées dans Android 7.x et versions antérieures.

Processus de création pour Android 7.x et versions antérieures

Les règles SELinux sont créées en combinant les règles AOSP de base avec des personnalisations spécifiques à l'appareil. Les règles combinées sont ensuite transmises au compilateur de règles et à différents vérificateurs. La personnalisation spécifique à l'appareil est effectuée via la variable BOARD_SEPOLICY_DIRS définie dans le fichier Boardconfig.mk spécifique à l'appareil. Cette variable de compilation globale contient une liste de répertoires qui spécifient l'ordre dans lequel rechercher des fichiers de règles supplémentaires.

Par exemple, un fournisseur de SoC et un ODM peuvent chacun ajouter un répertoire, l'un pour les paramètres spécifiques au SoC et l'autre pour les paramètres spécifiques à l'appareil, afin de générer les configurations SELinux finales pour un appareil donné :

  • BOARD_SEPOLICY_DIRS += device/SoC/common/sepolicy
  • BOARD_SEPOLICY_DIRS += device/SoC/DEVICE/sepolicy

Le contenu des fichiers file_contexts dans system/sepolicy et BOARD_SEPOLICY_DIRS est concaténé pour générer le file_contexts.bin sur l'appareil :

Logique de compilation SELinux pour Android 7.x

Figure 1. Logique de création SELinux.

Le fichier sepolicy se compose de plusieurs fichiers sources :

  • Le texte brut policy.conf est généré en concaténant security_classes, initial_sids, les fichiers *.te, genfs_contexts et port_contexts dans cet ordre.
  • Pour chaque fichier (tel que security_classes), son contenu est la concaténation des fichiers portant le même nom sous system/sepolicy/ et BOARDS_SEPOLICY_DIRS.
  • Le policy.conf est envoyé au compilateur SELinux pour vérification de la syntaxe et compilé au format binaire en tant que sepolicy sur l' appareil.

    Fichiers qui génèrent le fichier de règles SELinux
      pour Android 7.x
    Figure 2. Fichier de règles SELinux.

Fichiers SELinux

Après la compilation, les appareils Android exécutant la version 7.x ou une version antérieure contiennent généralement les fichiers liés à SELinux suivants :

  • selinux_version
  • sepolicy : sortie binaire après la combinaison de fichiers de règles (tels que security_classes, initial_sids, et *.te)
  • file_contexts
  • property_contexts
  • seapp_contexts
  • service_contexts
  • system/etc/mac_permissions.xml

Pour en savoir plus, consultez Implémenter SELinux.

Initialisation de SELinux

Lorsque le système démarre, SELinux est en mode permissif (et non en mode d'application forcée). Le processus d'initialisation effectue les tâches suivantes :

  • Charge les fichiers sepolicy du disque RAM dans le noyau via /sys/fs/selinux/load.
  • Passe SELinux en mode d'application forcée.
  • Exécute re-exec() pour appliquer la règle de domaine SELinux à elle-même.

Pour réduire le temps de démarrage, exécutez re-exec() sur le processus init dès que possible.

Android 8.0 et versions ultérieures

Dans Android 8.0, les règles SELinux sont divisées en composants de plate-forme et de fournisseur pour permettre des mises à jour indépendantes des règles de plate-forme et de fournisseur tout en maintenant la compatibilité.

La sepolicy de la plate-forme est divisée en parties privées et publiques pour exporter des types et des attributs spécifiques vers les rédacteurs de règles de fournisseur. Les types/attributs publics de la plate-forme sont garantis comme étant des API stables pour une version de plate-forme donnée. La compatibilité avec les types/attributs publics de la plate-forme précédente peut être garantie pour plusieurs versions à l'aide de fichiers de mappage de plate-forme.

Processus de création pour Android 8.0

Les règles SELinux dans Android 8.0 sont créées en combinant des éléments de /system et /vendor. La logique de configuration appropriée se trouve dans /platform/system/sepolicy/Android.bp.

Les règles se trouvent aux emplacements suivants :

Emplacement Contient
system/sepolicy/public API sepolicy de la plate-forme
system/sepolicy/private Détails d'implémentation de la plate-forme (les fournisseurs peuvent les ignorer)
system/sepolicy/vendor Fichiers de règles et de contexte que les fournisseurs peuvent utiliser (les fournisseurs peuvent les ignorer)
BOARD_SEPOLICY_DIRS sepolicy du fournisseur
BOARD_ODM_SEPOLICY_DIRS (Android 9 et versions ultérieures) sepolicy de l'ODM
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 et versions ultérieures) API sepolicy system_ext
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 et versions ultérieures) Détails d'implémentation system_ext (les fournisseurs peuvent les ignorer)
PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 et versions ultérieures) API sepolicy du produit
PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 et versions ultérieures) Détails d'implémentation du produit (les fournisseurs peuvent les ignorer)

Le système de compilation prend ces règles et produit des composants de règles system, system_ext, product, vendor, et odm sur la partition correspondante. Voici les étapes à suivre :

  1. Convertissez les règles au format SELinux Common Intermediate Language (CIL) format, en particulier:
    • Règles de plate-forme publiques (system, system_ext, product)
    • Règles privées et publiques combinées
    • Règles publiques, de fournisseur et BOARD_SEPOLICY_DIRS
  2. Versionnez les règles fournies par le public dans le cadre des règles de fournisseur. Utilisez les règles CIL publiques produites pour informer les règles publiques et de fournisseur combinées, ainsi que les règles BOARD_SEPOLICY_DIRS des parties qui doivent être transformées en attributs liés aux règles de la plate-forme.
  3. Créez un fichier de mappage liant les parties de la plate-forme et du fournisseur. Au départ, cela ne fait que lier les types des règles publiques aux attributs correspondants dans les règles de fournisseur. Plus tard, cela servira également de base au fichier conservé dans les futures versions de la plate-forme, ce qui permettra la compatibilité avec les règles de fournisseur ciblant cette version de la plate-forme.
  4. Combinez les fichiers de règles (décrivez les solutions sur l'appareil et précompilées).
    1. Combinez les règles de mappage, de plate-forme et de fournisseur.
    2. Compilez le fichier de règles binaires de sortie.

sepolicy publique de la plate-forme

La sepolicy publique de la plate-forme inclut tout ce qui est défini sous system/sepolicy/public. La plate-forme peut supposer que les types et les attributs définis dans les règles publiques sont des API stables pour une version de plate-forme donnée. Cela constitue la partie de la sepolicy qui est exportée par la plate-forme sur laquelle les développeurs de règles de fournisseur (c'est-à-dire d'appareil) peuvent écrire des règles supplémentaires spécifiques à l'appareil.

Les types sont versionnés en fonction de la version des règles par rapport auxquelles les fichiers de fournisseur sont écrits, définis par la variable de compilation PLATFORM_SEPOLICY_VERSION. Les règles publiques versionnées sont ensuite incluses dans les règles de fournisseur et (dans leur forme d'origine) dans les règles de la plate-forme. Ainsi, les règles finales incluent les règles de plate-forme privées, la sepolicy publique de la plate-forme actuelle, les règles spécifiques à l'appareil et les règles publiques versionnées correspondant à la version de la plate-forme par rapport à laquelle les règles de l'appareil ont été écrites.

sepolicy privée de la plate-forme

La sepolicy privée de la plate-forme inclut tout ce qui est défini sous /system/sepolicy/private. Cette partie des règles forme des types, des autorisations et des attributs propres à la plate-forme, requis pour les fonctionnalités de la plate-forme. Ils ne sont pas exportés vers les rédacteurs de règles de fournisseur et d'appareil. Les rédacteurs de règles non liés à la plate-forme ne doivent pas écrire leurs extensions de règles en fonction des types, des attributs et des règles définis dans la sepolicy privée de la plate-forme. De plus, ces règles peuvent être modifiées ou disparaître dans le cadre d'une mise à jour du framework uniquement.

Mappage privé de la plate-forme

Le mappage privé de la plate-forme inclut des instructions de règles qui mettent en correspondance les attributs exposés dans les règles publiques de la plate-forme des versions précédentes avec les types concrets utilisés dans la sepolicy publique de la plate-forme actuelle. Cela garantit que les règles de fournisseur écrites en fonction des attributs publics de la plate-forme des versions précédentes de la sepolicy publique de la plate-forme continuent de fonctionner. Le contrôle des versions est basé sur la variable de compilation PLATFORM_SEPOLICY_VERSION définie dans AOSP pour une version de plate-forme donnée. Un fichier de mappage distinct existe pour chaque version de plate-forme précédente à partir de laquelle cette plate-forme est censée accepter les règles de fournisseur. Pour en savoir plus, consultez Compatibilité des règles.

Android 11 et versions ultérieures

Cette section explique comment les règles SELinux sont créées dans Android 11 et versions ultérieures.

sepolicy system_ext et product

Dans Android 11, les règles system_ext et product sont ajoutées. Comme la sepolicy de la plate-forme, les règles system_ext et product sont divisées en règles publiques et privées.

Les règles publiques sont exportées vers le fournisseur. Les types et les attributs deviennent des API stables, et les règles de fournisseur peuvent faire référence aux types et aux attributs des règles publiques. Les types sont versionnés en fonction de PLATFORM_SEPOLICY_VERSION, et les règles versionnées sont incluses dans les règles de fournisseur. Les règles d'origine sont incluses dans chaque partition system_ext et product.

Les règles privées contiennent des types, des autorisations et des attributs propres à system_ext et à product, requis pour les fonctionnalités des partitions system_ext et product. Les règles privées sont invisibles pour le fournisseur, ce qui implique que ces règles sont internes et peuvent être modifiées.

Mappage system_ext et product

system_ext et product sont autorisés à exporter leurs types publics désignés vers le fournisseur. Toutefois, chaque partenaire est responsable du maintien de la compatibilité. Pour assurer la compatibilité, les partenaires peuvent fournir leurs propres fichiers de mappage qui mettent en correspondance les attributs versionnés des versions précédentes avec les types concrets utilisés dans la sepolicy publique actuelle :

  • Pour installer un fichier de mappage pour system_ext, placez un fichier CIL contenant les informations de mappage souhaitées dans {SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil, puis ajoutez system_ext_{ver}.cil à PRODUCT_PACKAGES.
  • Pour installer un fichier de mappage pour product, placez un fichier CIL contenant les informations de mappage souhaitées dans {PRODUCT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil, puis ajoutez product_{ver}.cil à PRODUCT_PACKAGES.

Consultez un exemple qui ajoute un fichier de mappage de la partition product d'un appareil Redbull.

Règles SELinux précompilées

Avant que init n'active SELinux, init collecte tous les fichiers CIL des partitions (system, system_ext, product, vendor et odm) et les compile en règles binaires, le format qui peut être chargé dans le noyau. Comme la compilation prend du temps (généralement 1 à 2 secondes), les fichiers CIL sont précompilés au moment de la compilation et placés dans /vendor/etc/selinux/precompiled_sepolicy ou /odm/etc/selinux/precompiled_sepolicy, avec les hachages sha256 des fichiers CIL d'entrée. Lors de l'exécution, init vérifie si l'un des fichiers de règles a été mis à jour en comparant les hachages. Si rien n'a changé, init charge les règles précompilées. Sinon, init compile à la volée et l'utilise à la place de la version précompilée.

Plus précisément, les règles précompilées sont utilisées si toutes les conditions suivantes sont remplies. Ici, {partition} représente la partition où se trouvent les règles précompilées : vendor ou odm.

  • /system/etc/selinux/plat_sepolicy_and_mapping.sha256 et /{partition}/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256 existent et sont identiques.
  • /system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256 et /{partition}/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256 n'existent pas. Ou les deux existent et sont identiques.
  • /product/etc/selinux/product_sepolicy_and_mapping.sha256 et /{partition}/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256 n'existent pas. Ou les deux existent et sont identiques.

Si l'un d'eux est différent, init revient au chemin de compilation sur l'appareil. Pour en savoir plus, consultez system/core/init/selinux.cpp.