Implémenter SELinux

SELinux est configuré sur default-deny, ce qui signifie que chaque accès dont il a un hook dans le noyau doit être explicitement autorisé par la stratégie. Cela signifie qu'un fichier de règles comprend une grande quantité d'informations sur les règles, les types, les classes, les autorisations, etc. Une analyse complète de SELinux n'entre pas dans le champ d'application de ce document, mais il est désormais essentiel de savoir écrire des règles de stratégie lors de la mise en service de nouveaux appareils Android. De nombreuses informations sont déjà disponibles sur SELinux. Pour obtenir des suggestions de ressources, consultez la section Documentation complémentaire.

Fichiers de clé

Pour activer SELinux, intégrez le dernière version Noyau Android, puis incorporez les fichiers présents system/sepolicy . Une fois compilés, ces fichiers constituent le composant de sécurité et couvrent le système d'exploitation Android en amont.

En règle générale, vous ne devez pas modifier directement les fichiers system/sepolicy. À la place, ajoutez ou modifiez vos propres fichiers de règles spécifiques à l'appareil dans le /device/manufacturer/device-name/sepolicy . Dans Android 8.0 et versions ultérieures, les modifications que vous apportez à ces fichiers doivent n'affectent que la stratégie dans votre répertoire de fournisseurs. Pour en savoir plus sur la séparation sepolicy publique sur Android 8.0 et versions ultérieures, voir Personnaliser SEPolicy sous Android 8.0 et versions ultérieures. Quelle que soit la version d'Android, vous êtes toujours en train de modifier les fichiers suivants:

Fichiers de règles

Les fichiers se terminant par *.te sont des fichiers sources de règles SELinux, qui définissent les domaines et leurs libellés. Vous devrez peut-être créer des fichiers de règles dans /device/manufacturer/device-name/sepolicy, mais vous devez essayer de mettre à jour les fichiers existants dans la mesure du possible.

Fichiers de contexte

Les fichiers de contexte vous permettent de spécifier des libellés pour vos objets.

  • file_contexts attribue des libellés aux fichiers et est utilisé par divers de l'espace utilisateur. Lorsque vous créez des règles, créez ou mettez à jour ce fichier pour attribuer de nouveaux libellés aux fichiers. Pour appliquer un nouveau file_contexts, recompilez l'image du système de fichiers ou exécutez restorecon sur le fichier pour à modifier leur libellé. Lors des mises à niveau, les modifications apportées à file_contexts sont automatiquement appliquée aux partitions système et userdata dans le cadre du mise à niveau. Les modifications peuvent aussi être appliquées automatiquement lors de la mise à niveau vers d'autres des partitions en ajoutant des appels restorecon_recursive à votre init.board.rc après l'installation de la partition en lecture/écriture.
  • genfs_contexts attribue des étiquettes aux systèmes de fichiers, comme proc ou vfat non compatibles avec les méthodes étendues . Cette configuration est chargée dans le cadre de la stratégie de noyau, mais les modifications peuvent ne pas prendre effet pour les nœuds de calcul intégrés, ce qui nécessite un redémarrage ou démonter et réinstaller le système de fichiers pour appliquer complètement la modification. Des libellés spécifiques peuvent également être attribués à des montages spécifiques, tels que vfat à l'aide de l'option context=mount.
  • property_contexts attribue des libellés aux propriétés du système Android pour contrôler les processus qui peuvent les définir. Cette configuration est lue par init au démarrage.
  • service_contexts attribue des étiquettes aux services de liaison Android pour contrôler quels processus peuvent ajouter (enregistrer) et trouver (rechercher) un binder référence pour le service. Cette configuration est lue par le processus servicemanager au démarrage.
  • seapp_contexts attribue des étiquettes aux processus de l'application et /data/data. Cette configuration est lue par le processus zygote à chaque lancement d'application et par installd au démarrage.
  • mac_permissions.xml attribue une balise seinfo aux applications en fonction de leur signature et éventuellement de leur nom de package. La balise seinfo peut ensuite être utilisée comme clé dans le fichier seapp_contexts pour attribuer un libellé spécifique à toutes les applications avec cette balise seinfo. Cette configuration est lue par system_server au démarrage.
  • keystore2_key_contexts attribue des étiquettes aux espaces de noms Keystore 2.0. Ces espaces de noms sont appliqués par le daemon keystore2. Le keystore a toujours fourni des espaces de noms basés sur des UID/AID. Keystore 2.0 applique également sepolicy et les espaces de noms définis. Pour en savoir plus sur le format et les conventions de ce fichier, cliquez ici.

Fichier makefile BoardConfig.mk

Après avoir modifié ou ajouté des fichiers de règles et de contexte, mettez à jour votre fichier de compilation /device/manufacturer/device-name/BoardConfig.mk pour référencer le sous-répertoire sepolicy et chaque nouveau fichier de règles. Pour en savoir plus sur les variables BOARD_SEPOLICY, consultez system/sepolicy/README.

BOARD_SEPOLICY_DIRS += \
        <root>/device/manufacturer/device-name/sepolicy

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

Une fois recompilé, SELinux est activé sur votre appareil. Vous pouvez désormais personnaliser vos règles SELinux pour prendre en charge vos propres ajouts au système d'exploitation Android, comme décrit dans la section Personnalisation, ou vérifier votre configuration existante, comme décrit dans la section Validation.

Une fois les nouveaux fichiers de stratégie et les mises à jour de BoardConfig.mk en place, le nouveau les paramètres des stratégies sont automatiquement intégrés dans le fichier final de stratégie du noyau. Pour en savoir plus sur la création de sepolicy sur l'appareil, consultez la section Créer sepolicy.

Implémentation

<ph type="x-smartling-placeholder">

Pour commencer à utiliser SELinux:

  1. Activez SELinux dans le noyau : CONFIG_SECURITY_SELINUX=y
  2. Modifiez le paramètre kernel_cmdline ou bootconfig comme suit:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    ou
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    Elle ne s'applique qu'au développement initial de la stratégie de l'appareil. Après avoir une règle d'amorçage initiale, supprimez ce paramètre pour que votre l'appareil ne fait pas l'application ou l'échec de la CTS.
  3. Démarrez le système en mode permissif et vérifiez les refus rencontrés au démarrage :
    Sous Ubuntu 14.04 ou version ultérieure :
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    Sous Ubuntu 12.04 :
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. Examinez la sortie pour rechercher des avertissements ressemblant à init: Warning! Service name needs a SELinux domain defined; please fix!. Consultez la section Validation pour obtenir des instructions et des outils.
  5. Identifiez les appareils et les autres nouveaux fichiers qui doivent être libellés.
  6. Utilisez des libellés existants ou créez-en des nouveaux pour vos objets. Consultez le *_contexts fichiers pour afficher l'ancien libellé et utilisez la connaissance de la signification des étiquettes pour en attribuer une nouvelle. Dans l’idéal, il s'agit d'un libellé existant qui entre dans le règlement, mais il arrive un nouveau libellé est nécessaire et les règles d'accès à ce libellé sont nécessaires. Ajoutez vos libellés aux fichiers de contexte appropriés.
  7. Identifiez les domaines/processus qui devraient disposer de leurs propres domaines de sécurité. Vous devrez probablement écrire une règle complètement différente pour chacune d'elles. Tout les services générés à partir de init, par exemple, doivent avoir leur vous-même. Les commandes suivantes permettent d'afficher celles qui sont toujours en cours d'exécution (mais TOUTES nécessitent un tel traitement):
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. Examinez init.device.rc pour identifier les domaines qui ne disposent pas d'un type de domaine. Attribuez-leur un domaine en avance dans votre de développement pour éviter d'ajouter des règles à init ou peut prêter à confusion init avec ceux qui se trouvent dans ses propres règles.
  9. Configurez BOARD_CONFIG.mk pour utiliser des variables BOARD_SEPOLICY_*. Consultez le LISEZ-MOI dans system/sepolicy pour en savoir plus sur la configuration.
  10. Examinez les fichiers init.device.rc et fstab.device, et assurez-vous que chaque utilisation de mount correspond à un système de fichiers correctement libellé ou qu'une option context= mount est spécifiée.
  11. Passez en revue chaque refus et créez une règle SELinux pour gérer correctement chacun d'eux. Voir les exemples de la section Personnalisation.

Vous devez commencer par les règles de l'AOSP, puis les développer pour vos propres personnalisations. Pour en savoir plus sur la stratégie de stratégie et pour examiner de plus près certaines de ces étapes, consultez la section Écrire des règles SELinux.

Cas d'utilisation

Voici des exemples spécifiques d'exploitation de failles à prendre en compte logiciels et les règles SELinux associées:

Liens symboliques : comme les liens symboliques apparaissent comme des fichiers, ils sont souvent lus comme des fichiers, ce qui peut entraîner des exploitations. Par exemple, certains composants privilégiés, tels que init, modifient les autorisations de certains fichiers, parfois de manière excessive.

Les pirates informatiques peuvent ensuite remplacer ces fichiers par des liens symboliques vers du code qu'ils contrôlent, ce qui leur permet d'écraser des fichiers arbitraires. Toutefois, si vous savez que votre application ne traverse jamais de lien symbolique, vous pouvez l'en empêcher avec SELinux.

Fichiers système : classe de fichiers système qui ne doivent être modifiés que par le serveur système. Toutefois, comme netd, init et vold s'exécutent en tant que racine, ils peuvent accéder à ces fichiers système. Par conséquent, si netd est compromis, il peut compromettre ces fichiers et potentiellement le serveur système lui-même.

Avec SELinux, vous pouvez identifier ces fichiers en tant que fichiers de données du serveur système. Par conséquent, le seul domaine disposant d'un accès en lecture/écriture est le serveur système. Même si la sécurité du domaine netd était compromise, il ne pourrait pas basculer les domaines vers le domaine du serveur système et accéder à ces fichiers système même s’il s’exécute en tant que racine.

Données d'application:un autre exemple est la classe de fonctions qui doit s'exécuter en tant que racine, mais ne devrait pas accéder aux données de l'application. C'est incroyablement car il est possible d'effectuer des assertions étendues (par exemple, certains domaines sans rapport aux données d'applications qui n'ont pas accès à Internet.

setattr:pour les commandes telles que chmod et chown, vous pourriez identifier l'ensemble de fichiers auquel domaine peut effectuer setattr. Tout ce qui n'est pas inclus peut être interdit, même par le root. Par conséquent, une application peut exécuter chmod et chown sur les éléments marqués app_data_files, mais pas sur shell_data_files ou system_data_files.