Créer une règle SELinux

Cette page explique comment la règle SELinux est créée. 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 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 la plate-forme et du fournisseur sont créées séparément. Les SoC et les OEM peuvent mettre à jour leurs sections du règlement, 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 monter les partitions system et vendor plus tôt afin de pouvoir lire les fichiers SELinux de ces partitions et les fusionner avec les fichiers SELinux principaux 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éterminez si un contexte de sécurité est valide pour une règle 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 de l'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 la stratégie SELinux Android de base, y compris les contextes et les fichiers de stratégie. La logique de compilation sepolicy majeure 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 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 à différents vérificateurs. La personnalisation spécifique à l'appareil s'effectue 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 fichier file_contexts.bin sur l'appareil :

Logique de compilation SELinux pour Android 7.x

Figure 1. Logique de compilation SELinux.

Le fichier sepolicy se compose de plusieurs fichiers sources :

  • Le fichier policy.conf en texte brut est généré en concaténant les fichiers security_classes, initial_sids, *.te, genfs_contexts et port_contexts dans cet ordre.
  • Pour chaque fichier (par exemple, security_classes), son contenu est la concaténation des fichiers portant le même nom sous system/sepolicy/ et BOARDS_SEPOLICY_DIRS.
  • Le fichier policy.conf est envoyé au compilateur SELinux pour vérification de la syntaxe et compilé au format binaire 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 compilation, les appareils Android 7.x et versions antérieures contiennent généralement les fichiers SELinux suivants :

  • selinux_version
  • sepolicy : sortie binaire après la 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

Au démarrage du système, 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 du disque RAM dans le noyau via /sys/fs/selinux/load.
  • Passe SELinux en mode d'application.
  • Exécute re-exec() pour appliquer la règle de domaine SELinux à lui-même.

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

Android 8.0 ou version ultérieure

Dans Android 8.0, la règle SELinux est divisée 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 plate-forme sepolicy est en outre divisée en parties privées et publiques pour exporter des types et des attributs spécifiques vers les rédacteurs de règles du fournisseur. Les types/attributs publics de la plate-forme sont garantis comme étant des API stables pour une version donnée de la plate-forme. 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 pour configurer correctement cette fonctionnalité se trouve dans /platform/system/sepolicy/Android.bp.

La règle existe aux emplacements suivants :

Position Contient
system/sepolicy/public API sepolicy de la plate-forme
system/sepolicy/private Détails de l'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 (ou ignorer)
BOARD_SEPOLICY_DIRS sepolicy du fournisseur
BOARD_ODM_SEPOLICY_DIRS (Android 9 ou version ultérieure) ODM sepolicy
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) system_ext Informations sur l'implémentation (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) Informations sur l'implémentation du produit (les fournisseurs peuvent les ignorer)

Le système de compilation prend cette stratégie et produit les composants de stratégie 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), plus précisément :
    • Règlement de la plate-forme publique (system, system_ext, product)
    • Règlement combinant les paramètres privés et publics
    • Règles publiques, relatives aux fournisseurs et BOARD_SEPOLICY_DIRS
  2. Versionnez le règlement fourni par le public dans le règlement relatif aux fournisseurs. Utilisez la règle CIL publique produite pour informer la règle combinée publique et BOARD_SEPOLICY_DIRS du fournisseur quant aux parties qui doivent être transformées en attributs liés à la règle de la plate-forme.
  3. Créez un fichier de mappage qui associe les parties de la plate-forme et du fournisseur. Au départ, cela ne fait que relier les types de la règle publique aux attributs correspondants de la règle du 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 la règle du fournisseur ciblant cette version de la plate-forme.
  4. Combiner des fichiers de règles (décrire les solutions sur l'appareil et précompilées)
    1. Combinez les règles de mappage, de plate-forme et du fournisseur.
    2. Compilez le fichier de stratégie binaire de sortie.

Stratégie de sécurité publique de la plate-forme

La règle de plate-forme publique SELinux 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 le règlement sont des API stables pour une version donnée de la plate-forme. Cela constitue la partie de la stratégie SELinux qui est exportée par la plate-forme sur laquelle les développeurs de stratégies de fournisseur (c'est-à-dire d'appareil) peuvent écrire des stratégies supplémentaires spécifiques à l'appareil.

Les types sont versionnés en fonction de la version de la règle par rapport à laquelle les fichiers du fournisseur sont écrits, définie par la variable de compilation PLATFORM_SEPOLICY_VERSION. La version de la règle publique est ensuite incluse dans 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 SELinux 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é rédigée.

sepolicy privé de la plate-forme

La stratégie SELinux privée de la plate-forme inclut tout ce qui est défini sous /system/sepolicy/private. Cette partie du règlement décrit les types, les autorisations et les attributs propres à la plate-forme qui sont nécessaires à son fonctionnement. Elles ne sont pas exportées vers les rédacteurs de règles concernant les fournisseurs et les appareils. Les rédacteurs de règles non liés à la plate-forme ne doivent pas rédiger leurs extensions de règles en fonction des types, des attributs et des règles définis dans la stratégie SE 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ègle qui mappent les attributs exposés dans la règle publique de la plate-forme des versions précédentes de la plate-forme aux types concrets utilisés dans la règle publique de la plate-forme actuelle. Cela garantit que le règlement du fournisseur rédigé sur la base des attributs publics de la plate-forme à partir des versions publiques précédentes de sepolicy de la plate-forme 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 précédente de la plate-forme à partir de laquelle cette plate-forme est censée accepter le règlement du fournisseur. Pour en savoir plus, consultez Compatibilité des règles.

Android 11 ou version ultérieure

Cette section explique comment la règle SELinux est créée dans Android 11 et versions ultérieures.

system_ext et sepolicy du produit

Dans Android 11, les règles system_ext et product ont été ajoutées. Comme la politique de la plate-forme, les politiques system_ext et product sont divisées en politique publique et politique privée.

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

La règle de confidentialité contient les types, les autorisations et les attributs system_ext uniquement et product uniquement requis pour la fonctionnalité de partition system_ext et product. Les règles de confidentialité ne sont pas visibles par le fournisseur, ce qui implique qu'elles 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, chaque partenaire est responsable du maintien de la compatibilité. Pour assurer la compatibilité, les partenaires peuvent fournir leurs propres fichiers de mappage qui associent les attributs versionnés des versions précédentes aux types concrets utilisés dans la stratégie SELinux 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ègle SELinux précompilée

Avant que init n'active SELinux, il collecte tous les fichiers CIL des partitions (system, system_ext, product, vendor et odm) et les compile en une règle binaire, le format qui peut ê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. 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 la stratégie précompilée. Sinon, init compile le fichier à la volée et l'utilise à la place de celui précompilé.

Plus précisément, une règle précompilée est utilisée si toutes les conditions suivantes sont remplies. Ici, {partition} représente la partition dans laquelle la règle 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'une d'elles est différente, init revient au chemin de compilation sur l'appareil. Pour en savoir plus, consultez system/core/init/selinux.cpp.