Créer une règle SELinux

Cette page explique comment créer une stratégie SELinux. La règle SELinux est créée à partir de la combinaison de la règle AOSP de base (plate-forme) et de la règle spécifique à l'appareil (fournisseur). Le flux de compilation 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 ODM modifiaient boot.img (pour les appareils autres que A/B) ou system.img (pour les appareils A/B) chaque fois que la règle était modifiée.

Sous Android 8.0 ou version ultérieure, les règles de la plate-forme et du fournisseur sont compilées séparément. Les SOC et les OEM peuvent mettre à jour leur partie du règlement, créer leurs images (par exemple, 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 modulaire sont stockés sur des partitions /vendor, le processus init doit installer les partitions système et du fournisseur plus tôt afin de pouvoir lire les fichiers SELinux à partir de ces partitions et les fusionner avec les fichiers SELinux principaux dans le répertoire système (avant de les charger dans le noyau).

Fichiers sources

La logique de compilation 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 stratégie binaire donnée (exécutable hôte).
      • libsepol: bibliothèque SELinux permettant de 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 base des règles SELinux Android, y compris les contextes et les fichiers de règles. La logique de compilation principale de sepolicy est également ici (system/sepolicy/Android.mk).

Pour en savoir plus sur les fichiers dans system/sepolicy, consultez Implémenter SELinux.

Android 7.x et versions antérieures

Cette section explique comment la règle SELinux est créée dans Android 7.x et versions antérieures.

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

La règle SELinux est créée en combinant la règle AOSP de base avec des personnalisations spécifiques à l'appareil. La règle combinée est ensuite transmise au compilateur de règles et à divers outils de vérification. 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:

Cette image montre la logique de compilation SELinux pour Android 7.x.

Figure 1 : Logique de compilation SELinux.

Le fichier sepolicy se compose de plusieurs fichiers sources:

  • Le texte brut policy.conf est généré en concatenant les fichiers security_classes, initial_sids, *.te, genfs_contexts et port_contexts dans cet ordre.
  • Pour chaque fichier (par exemple, security_classes), son contenu correspond à 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.
    Cette image montre les 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 compilation, les appareils Android exécutant la version 7.x ou antérieure contiennent généralement les fichiers liés à SELinux suivants:

  • selinux_version
  • sepolicy: sortie binaire après combinaison des fichiers de règles (par exemple, 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 init effectue les tâches suivantes:

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

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

Android 8.0 ou version ultérieure

Dans Android 8.0, la stratégie SELinux est divisée en composants de plate-forme et de fournisseur pour permettre des mises à jour de stratégie de plate-forme/fournisseur indépendantes tout en conservant la compatibilité.

La stratégie de sécurité de la plate-forme est ensuite divisée en parties privées et publiques pour exporter des types et des attributs spécifiques aux auteurs de règles du fournisseur. Les types/attributs publics de la plate-forme sont garantis comme 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 compilation pour Android 8.0

La règle SELinux dans Android 8.0 est créée en combinant des éléments de /system et /vendor. La logique de configuration appropriée se trouve dans /platform/system/sepolicy/Android.mk.

La règle se trouve aux emplacements suivants:

Position Contient
system/sepolicy/public L'API sepolicy de la plate-forme
system/sepolicy/private Détails de l'implémentation de la plate-forme (les fournisseurs peuvent ignorer)
system/sepolicy/vendor Fichiers de règles et de contexte que les fournisseurs peuvent utiliser (ils peuvent les ignorer s'ils le souhaitent)
BOARD_SEPOLICY_DIRS Politique de sécurité du fournisseur
BOARD_ODM_SEPOLICY_DIRS (Android 9 ou version ultérieure) Odm sepolicy
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 ou version ultérieure) API sepolicy de System_ext
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 ou version ultérieure) Détails de l'implémentation de System_ext (les fournisseurs peuvent ignorer)
PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 ou version ultérieure) API sepolicy du produit
PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 ou version ultérieure) Informations sur l'implémentation du produit (les fournisseurs peuvent ignorer cette section)

Le système de compilation prend cette stratégie et produit des composants de stratégie système, system_ext, produit, fournisseur et odm sur la partition correspondante. Voici les étapes à suivre:

  1. Convertir les règles au format CIL (Common Intermediate Language) de SELinux, en particulier :
    1. Règles de la plate-forme publique (system + system_ext + product)
    2. règles privées et publiques combinées
    3. public + vendor and BOARD_SEPOLICY_DIRS policy
  2. Gérer les versions de la règle fournie par le public dans le cadre de la règle du fournisseur. Cela se fait en utilisant la règle publique de CIL produite pour indiquer à la règle publique + fournisseur + BOARD_SEPOLICY_DIRS quelles parties doivent être transformées en attributs qui seront associés à la règle de la plate-forme.
  3. Créer un fichier de mappage reliant les parties de la plate-forme et du fournisseur. Au départ, cela ne fait que lier les types de la règle publique aux attributs correspondants dans la règle du fournisseur. Par la suite, il servira également de base au fichier géré dans les futures versions de la plate-forme, ce qui permettra la compatibilité avec la règle du fournisseur ciblant cette version de la plate-forme.
  4. Combiner des fichiers de règles (décrit à la fois les solutions sur l'appareil et les solutions précompilées).
    1. Combinez les règles de cartographie, de plate-forme et de fournisseur.
    2. Compilez le fichier de stratégie binaire de sortie.

Politique de sécurité publique de la plate-forme

La règle de sécurité 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 attributs définis dans le règlement public sont des API stables pour une version de plate-forme donnée. Cela fait partie de la sepolicy 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 numérotés en fonction de la version de la règle à laquelle les fichiers du fournisseur sont écrits, définie par la variable de compilation PLATFORM_SEPOLICY_VERSION. La règle publique versionnée est ensuite incluse avec la règle du fournisseur et (dans sa forme d'origine) dans la règle de la plate-forme. Ainsi, la règle finale inclut la règle de plate-forme privée, la règle de sécurité publique de la plate-forme actuelle, la règle spécifique à l'appareil et la règle publique versionnée correspondant à la version de la plate-forme pour laquelle la règle de l'appareil a été écrite.

Stratégie de sécurité privée de la plate-forme

La stratégie de sécurité privée de la plate-forme inclut tout ce qui est défini sous /system/sepolicy/private. Cette partie de la stratégie définit les types, les autorisations et les attributs réservés à la plate-forme, qui sont nécessaires à son fonctionnement. Ils ne sont pas exportés vers les outils d'écriture de règles vendor/device. Les auteurs de règles non liées à la plate-forme ne doivent pas écrire leurs extensions de règles en fonction des types/attributs/règles définis dans la plate-forme privée sepolicy. De plus, ces règles peuvent être modifiées ou peuvent disparaître lors d'une mise à jour du framework uniquement.

Cartographie privée de la plate-forme

Le mappage privé de la plate-forme inclut des instructions de stratégie qui mappent les attributs exposés dans la stratégie publique de la plate-forme des versions précédentes de la plate-forme aux types concrets utilisés dans la stratégie publique actuelle de la plate-forme. Cela garantit que la stratégie du fournisseur écrite en fonction des attributs publics de la plate-forme des versions précédentes de la plate-forme sepolicy publique continue de fonctionner. La gestion des versions est basée 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 doit accepter la stratégie du fournisseur. Pour en savoir plus, consultez la section Compatibilité.

Android 11 ou version ultérieure

system_ext et product sepolicy

Sous Android 11, les règles system_ext et product sont ajoutées. Comme la stratégie sepolicy de la plate-forme, la stratégie system_ext et la stratégie produit sont divisées en stratégie publique et stratégie privée.

Le règlement public est exporté vers le fournisseur. Les types et les attributs deviennent une API stable, et la règle du fournisseur peut faire référence aux types et aux attributs dans la règle publique. Les types sont versionnés selon PLATFORM_SEPOLICY_VERSION, et la stratégie versionnée est incluse dans la stratégie du fournisseur. La stratégie d'origine est incluse dans chaque partition system_ext et product.

La stratégie privée contient des types, des autorisations et des attributs réservés à system_ext et aux produits, qui sont nécessaires au fonctionnement des partitions system_ext et produit. Les règles privées sont invisibles pour le fournisseur, ce qui implique que ces règles sont internes et peuvent être modifiées.

Mise en correspondance de system_ext et des produits

system_ext et product sont autorisés à exporter leurs types publics désignés vers le fournisseur. Toutefois, la responsabilité de maintenir la compatibilité incombe à chaque partenaire. Pour des raisons de compatibilité, les partenaires peuvent fournir leurs propres fichiers de mappage qui mappent les attributs versionnés des versions précédentes sur des types concrets utilisés dans la politique de sécurité 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 un produit, 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 cet exemple qui ajoute un fichier de mappage de la partition de produits de l'appareil Redbull.

Règle SELinux précompilée

Avant que init n'active SELinux, il rassemble tous les fichiers CIL des partitions (system, system_ext, product, vendor et odm) et les compile en règles binaires, le format pouvant être chargé dans le noyau.init Comme la compilation prend du temps (généralement une à deux 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. Au moment de l'exécution, init vérifie si le fichier de règles a été mis à jour en comparant les hachages. Si rien n'a changé, init charge la stratégie précompilée. Sinon, init compile le code à la volée et l'utilise à la place du code précompilé.

Plus précisément, la règle précompilée est utilisée si toutes les conditions suivantes sont remplies. Ici, {partition} représente la partition où la stratégie précompilée existe: 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 utilise le chemin de compilation sur l'appareil. Pour en savoir plus, consultez system/core/init/selinux.cpp.