Rédiger une stratégie SELinux

Le projet Android Open Source (AOSP) fournit une stratégie de base solide pour le applications et services communs à tous les appareils Android. Les contributeurs d'AOSP affinent régulièrement ce règlement. La stratégie de base est attendue représente environ 90 à 95% de la règle finale sur l'appareil, personnalisées, soit les 5 à 10 % restants. Cet article se concentre sur ces personnalisations propres à l'appareil, comment écrire une stratégie spécifique certains des pièges à éviter en cours de route.

Affichage de l'appareil

Pour rédiger une règle spécifique à un appareil, procédez comme suit :

Exécuter en mode permissif

Lorsqu'un appareil est connecté mode permissif, les refus sont consignés, mais pas appliquées. Le mode permissif est important raisons:

  • Le mode permissif permet de s'assurer que la modification des règles ne retarde pas les autres de récupération de l'appareil.
  • Un refus forcé peut masquer d'autres refus. Par exemple, l'accès aux fichiers implique généralement une recherche de répertoire, l'ouverture d'un fichier, puis la lecture d'un fichier. Dans seul le refus de la recherche de répertoire se produira. Permissif permet de s'assurer que tous les refus sont visibles.

Le moyen le plus simple de passer un appareil en mode permissif est d'utiliser le commande kernel ligne. Cet élément peut être ajouté au fichier BoardConfig.mk de l'appareil: platform/device/<vendor>/<target>/BoardConfig.mk Après avoir modifié la ligne de commande, exécutez make clean, puis make bootimage, puis flashez la nouvelle image de démarrage.

Confirmez ensuite le mode permissif avec:

adb shell getenforce

Une période de deux semaines est un délai raisonnable pour être en mode permissif global. Une fois que vous avez résolu la majorité des refus, repassez à l'étape d'application corriger les insectes dès leur apparition. Les domaines continuent à générer des refus ou à fournir des services en développement intensif peut être temporairement mis en mode permissif, mais déplacer au mode application forcée dès que possible.

Appliquer tôt

En mode "Enforcing", les refus sont à la fois consignés et appliqués. Il est préférable afin de mettre votre appareil en mode application forcée le plus tôt possible. En attente de créer et appliquer des règles spécifiques à l'appareil entraîne souvent des bugs et une mauvaise expérience utilisateur. Commencez suffisamment tôt pour participer à version dogfood et garantir une couverture de test complète des fonctionnalités dans des cas d'utilisation réels. Démarrage... plus tôt permet de s'assurer que les préoccupations de sécurité éclairent les décisions de conception. À l'inverse, le fait d'accorder les autorisations basées uniquement sur les refus observés est une approche risquée. Utiliser ceci de temps pour réaliser un audit de sécurité de l'appareil et signaler les bugs liés aux comportements qui ne devraient pas être autorisés.

Supprimer ou supprimer une règle existante

Il existe un certain nombre de bonnes raisons de créer une règle spécifique à l'appareil à partir de sur un nouvel appareil, y compris:

Gérer les refus de services principaux

Les refus générés par les services principaux sont généralement traités par l'ajout de libellés aux fichiers. Exemple :

avc: denied { open } for pid=1003 comm=”mediaserver” path="/dev/kgsl-3d0”
dev="tmpfs" scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0
tclass=chr_file permissive=1
avc: denied { read write } for pid=1003 name="kgsl-3d0" dev="tmpfs"
scontext=u:r:mediaserver:s0
tcontext=u:object_r:device:s0 tclass=chr_file permissive=1

est complètement résolu en étiquetant /dev/kgsl-3d0 correctement. Dans Dans cet exemple, tcontext est device. Cela représente contexte par défaut où tout ce qui se trouve dans /dev reçoit le " appareil", sauf si un libellé plus spécifique lui est attribué. Accepter simplement la sortie de audit2allow entraînerait une règle incorrecte et trop permissive.

Pour résoudre ce type de problème, attribuez au fichier un libellé plus spécifique, qui dans ce cas est <ph type="x-smartling-placeholder"></ph> gpu_device. Aucune autre autorisation n'est nécessaire, car <ph type="x-smartling-placeholder"></ph> Mediaserver dispose déjà des autorisations nécessaires dans la stratégie de base pour accéder gpu_device.

Les autres fichiers spécifiques à l'appareil qui doivent être libellés avec des types prédéfinis dans règlement principal:

En général, l'attribution d'autorisations aux étiquettes par défaut est incorrecte. Nombre d'entre elles autorisations ne sont pas autorisées par neverallow, mais même s'ils ne sont pas explicitement interdits, il est recommandé de fournir un libellé.

Ajouter un libellé aux nouveaux services et aux nouvelles adresses refus

Les services lancés au démarrage doivent s'exécuter dans leurs propres domaines SELinux. La L'exemple suivant place le service "foo" dans son propre domaine SELinux et lui accorde autorisations.

Le service est lancé dans le init.device.rc en tant que:

service foo /system/bin/foo
    class core
  1. Créer le domaine "foo"

    Créer le fichier device/manufacturer/device-name/sepolicy/foo.te avec le contenu suivant:

    # foo service
    type foo, domain;
    type foo_exec, exec_type, file_type;
    
    init_daemon_domain(foo)
    

    Il s'agit du modèle initial du domaine SELinux "foo", sur lequel vous pouvez ajouter des règles basées sur les opérations spécifiques effectuées par cet exécutable.

  2. Libellé : /system/bin/foo

    Ajoutez le code suivant à device/manufacturer/device-name/sepolicy/file_contexts:

    /system/bin/foo   u:object_r:foo_exec:s0
    

    Cela garantit que l’exécutable est correctement étiqueté afin que SELinux exécute le dans le domaine approprié.

  3. Créez et flashez les images de démarrage et système.
  4. Affinez les règles SELinux du domaine.

    Utilisez les refus pour déterminer les autorisations requises. La audit2allow fournit de bonnes lignes directrices, mais ne les utilisez que pour élaborer des stratégies l'écriture. Ne vous contentez pas de copier le résultat.

Revenir au mode d'application forcée

Vous pouvez résoudre les problèmes en mode permissif, mais recommencez à appliquer le plus tôt possible et essayez d'y rester.

Erreurs courantes

Voici quelques solutions aux erreurs courantes qui se produisent lors de la rédaction règles spécifiques à chaque appareil.

Utilisation excessive de la négation

L'exemple de règle suivant revient à verrouiller la porte d'entrée fenêtres ouvertes:

allow { domain -untrusted_app } scary_debug_device:chr_file rw_file_perms

L'intention est claire: tout le monde, sauf les applications tierces, peut avoir accès au débogage appareil.

La règle présente des défauts pour plusieurs raisons. L'exclusion de untrusted_app est simple à contourner, car toutes les applications peuvent éventuellement exécuter des services dans isolated_app. De même, si de nouveaux domaines d'applications tierces sont ajoutés à AOSP, ils auront également accès à scary_debug_device. La règle est trop permissive. Pour la plupart des domaines, l'accès à cet outil de débogage. La règle aurait dû être écrite pour n'autoriser les domaines nécessitant un accès.

Fonctionnalités de débogage en production

Les fonctionnalités de débogage ne doivent pas être présentes sur les builds de production, .

L'alternative la plus simple consiste à n'autoriser la fonctionnalité de débogage que lorsque SELinux est désactivé sur les versions eng/userdebug, telles que adb root et adb shell setenforce 0

Une autre solution sûre consiste à placer les autorisations de débogage dans <ph type="x-smartling-placeholder"></ph> userdebug_or_eng.

Évolutivité de la taille de la règle

Caractériser les règles SEAndroid à l'état sauvage décrit une tendance préoccupante concernant la croissance de la personnalisation des règles relatives aux appareils. Les règles spécifiques à l'appareil devraient représenter 5 à 10% de l'ensemble des règles exécutées sur un appareil. Les personnalisations de plus de 20%contiennent presque certainement plus de les domaines privilégiés et les règles mortes.

Règle inutilement volumineuse:

  • Prend un double appel sur la mémoire lorsque la stratégie se trouve dans le ramdisk également chargé dans la mémoire du noyau.
  • Elle gaspille de l'espace disque en nécessitant une image de démarrage plus grande.
  • Affecte les temps de recherche des règles d'exécution.

L'exemple suivant présente deux appareils pour lesquels le paramètre représentaient 50% et 40% du règlement sur les appareils. Une réécriture de la règle a permis d'améliorer considérablement la sécurité sans perte de fonctionnalité, comme indiqué ci-dessous. (Les appareils AOSP Shamu et Flounder sont inclus à titre de comparaison.)

Figure 1: Comparaison de la taille des règles spécifiques aux appareils après l&#39;audit de sécurité

Figure 1 : Comparaison des caractéristiques par appareil la taille de la stratégie après l'audit de sécurité.

Dans les deux cas, le règlement a été considérablement réduit, tant en termes de taille que de nombre d'autorisations. La diminution de la taille des règles est presque entièrement due à la suppression des autorisations inutiles, dont beaucoup sont probablement des règles audit2allow qui ont été ajoutés sans distinction au règlement. Mort domaines posaient également un problème pour les deux appareils.

Accorder la fonctionnalité dac_override

Un refus dac_override signifie que le processus incriminé est d’accéder à un fichier avec les autorisations utilisateur/groupe/monde Unix incorrectes. La bonne solution consiste presque jamais à accorder l'autorisation dac_override. À la place, <ph type="x-smartling-placeholder"></ph> modifier les autorisations Unix sur le fichier ou le processus ; Quelques domaines tels que init, vold et installd ont réellement besoin la possibilité d’ignorer les autorisations de fichier Unix pour accéder aux fichiers d’autres processus. Lire le blog de Dan Walsh pour une explication plus détaillée.