Compatibilité des politiques

Cet article décrit comment Android gère les problèmes de compatibilité des politiques avec les plates-formes OTA, où les nouveaux paramètres SELinux de la plate-forme peuvent différer des paramètres SELinux de l'ancien fournisseur.

La conception de la politique SELinux basée sur les aigus tient compte d'une distinction binaire entre la politique de la plate-forme et celle du fournisseur ; le schéma devient plus compliqué si les partitions du fournisseur génèrent des dépendances, telles que platform < vendor < oem .

Dans Android 8.0 et versions ultérieures, la stratégie globale SELinux est divisée en composants privés et publics. Les composants publics sont constitués de la politique et de l'infrastructure associée, dont la disponibilité est garantie pour une version de plate-forme. Cette politique sera exposée aux rédacteurs de politique du fournisseur pour permettre aux fournisseurs de créer un fichier de politique du fournisseur qui, lorsqu'il est combiné avec la politique fournie par la plate-forme, se traduit par une politique entièrement fonctionnelle pour un appareil.

  • Pour la gestion des versions, la stratégie publique de plate-forme exportée sera écrite sous la forme d'attributs .
  • Pour faciliter l'écriture de la politique, les types exportés seront transformés en attributs versionnés dans le cadre du processus de création de la politique. Les types publics peuvent également être utilisés directement dans les décisions d'étiquetage fournies par les fichiers de contextes des fournisseurs.

Android maintient un mappage entre les types concrets exportés dans la stratégie de plate-forme et les attributs versionnés correspondants pour chaque version de plate-forme . Cela garantit que lorsque des objets sont étiquetés avec un type, cela ne rompt pas le comportement garanti par la politique publique de la plate-forme dans une version précédente. Ce mappage est maintenu en gardant un fichier de mappage à jour pour chaque version de la plate-forme , qui conserve les informations d'appartenance d'attribut pour chaque type exporté dans la politique publique.

Propriété et étiquetage des objets

Lors de la personnalisation de la politique dans Android 8.0 et versions ultérieures, la propriété doit être clairement définie pour chaque objet afin de séparer la politique de la plate-forme et celle du fournisseur. Par exemple, si le fournisseur étiquette /dev/foo et que la plate-forme étiquette ensuite /dev/foo dans un OTA ultérieur, il y aura un comportement indéfini. Pour SELinux, cela se manifeste par une collision d'étiquetage. Le nœud de périphérique ne peut avoir qu'une seule étiquette qui correspond à l'étiquette appliquée en dernier. Par conséquent:

  • Les processus qui ont besoin d'accéder à l'étiquette appliquée sans succès perdront l'accès à la ressource.
  • Les processus qui accèdent au fichier peuvent s'arrêter parce que le mauvais nœud de périphérique a été créé.

Les propriétés système ont également un potentiel de collisions de noms qui pourraient entraîner un comportement indéfini sur le système (ainsi que pour l'étiquetage SELinux). Des collisions entre les étiquettes de plate-forme et de fournisseur peuvent se produire pour tout objet qui a une étiquette SELinux, y compris les propriétés, les services, les processus, les fichiers et les sockets. Pour éviter ces problèmes, définissez clairement la propriété de ces objets.

En plus des collisions d'étiquettes, les noms de type/attribut SELinux peuvent également entrer en collision. Une collision type/nom d'attribut entraînera toujours une erreur du compilateur de stratégie.

Espacement des noms de type/attribut

SELinux n'autorise pas plusieurs déclarations du même type/attribut. La stratégie avec des déclarations en double échouera à la compilation. Pour éviter les conflits de types et de noms d'attributs, toutes les déclarations de fournisseur doivent avoir un espace de noms commençant par np_ .

type foo, domain; → type np_foo, domain;

Propriété du système et propriété de l'étiquetage des processus

Éviter les collisions d'étiquetage est mieux résolu en utilisant les espaces de noms de propriété. Pour identifier facilement les propriétés de plate-forme et éviter les conflits de noms lors du changement de nom ou de l'ajout de propriétés de plate-forme exportées, assurez-vous que toutes les propriétés de fournisseur ont leurs propres préfixes :

Type de propriété Préfixes acceptables
propriétés de contrôle ctl.vendor.
ctl.start$vendor.
ctl.stop$vendor.
init.svc.vendor.
lecture-écriture vendor.
lecture seulement ro.vendor.
ro.boot.
ro.hardware.
persistant persist.vendor.

Les fournisseurs peuvent continuer à utiliser ro.boot.* (qui provient de la ligne de commande du noyau) et ro.hardware.* (une propriété évidente liée au matériel).

Tous les services du fournisseur dans les fichiers init rc doivent avoir vendor. pour les services dans les fichiers init rc des partitions non système. Des règles similaires sont appliquées aux étiquettes SELinux pour les propriétés du fournisseur ( vendor_ pour les propriétés du fournisseur).

Propriété du fichier

La prévention des collisions pour les fichiers est difficile car la politique de la plate-forme et du fournisseur fournit généralement des étiquettes pour tous les systèmes de fichiers. Contrairement à la dénomination des types, l'espacement des noms de fichiers n'est pas pratique car nombre d'entre eux sont créés par le noyau. Pour éviter ces collisions, suivez les instructions de dénomination des systèmes de fichiers dans cette section. Pour Android 8.0, il s'agit de recommandations sans application technique. À l'avenir, ces recommandations seront appliquées par la Vendor Test Suite (VTS).

Système (/système)

Seule l'image système doit fournir des étiquettes pour les composants /system via file_contexts , service_contexts , etc. Si des étiquettes pour les composants /system sont ajoutées dans la politique /vendor , une mise à jour OTA du framework uniquement peut ne pas être possible.

Vendeur (/vendeur)

La politique AOSP SELinux étiquette déjà les parties de la partition vendor avec lesquelles la plate-forme interagit, ce qui permet d'écrire des règles SELinux pour que les processus de la plate-forme puissent parler et/ou accéder à des parties de la partition vendor . Exemples:

/vendor Libellé fourni par la plate-forme Processus de la plateforme en fonction du label
/vendor(/. * )? vendor_file Tous les clients HAL dans framework, ueventd , etc.
/vendor/framework(/. * )? vendor_framework_file dex2oat , appdomain , etc.
/vendor/app(/. * )? vendor_app_file dex2oat , installd , idmap , etc.
/vendor/overlay(/. * ) vendor_overlay_file system_server , zygote , idmap , etc.

Par conséquent, des règles spécifiques doivent être suivies (appliquées via neverallows ) lors de l'étiquetage de fichiers supplémentaires dans la partition vendor :

  • vendor_file doit être le libellé par défaut de tous les fichiers de la partition vendor . La politique de la plate-forme l'exige pour accéder aux implémentations HAL de relais.
  • Tous les nouveaux exec_types ajoutés dans la partition vendor via SEPolicy fournisseur doivent avoir l'attribut vendor_file_type . Ceci est appliqué par Neverallows.
  • Pour éviter les conflits avec les futures mises à jour de plate-forme/framework, évitez d'étiqueter des fichiers autres que exec_types dans la partition vendor .
  • Toutes les dépendances de bibliothèque pour les mêmes HAL de processus identifiés par AOSP doivent être étiquetées comme same_process_hal_file.

Procfs (/proc)

Les fichiers dans /proc peuvent être étiquetés en utilisant uniquement l'étiquette genfscon . Dans Android 7.0, la plate-forme et la politique du fournisseur utilisaient genfscon pour étiqueter les fichiers dans procfs .

Recommandation : Uniquement les étiquettes de stratégie de plate-forme /proc . Si les processus vendor ont besoin d'accéder aux fichiers dans /proc qui sont actuellement étiquetés avec l'étiquette par défaut ( proc ), la stratégie du fournisseur ne doit pas les étiqueter explicitement et doit plutôt utiliser le type proc générique pour ajouter des règles pour les domaines du fournisseur. Cela permet aux mises à jour de la plate-forme de prendre en charge les futures interfaces du noyau exposées via procfs et de les étiqueter explicitement selon les besoins.

Debugfs (/sys/kernel/debug)

Debugfs peut être étiqueté à la fois dans file_contexts et genfscon . Dans Android 7.0 à Android 10, debugfs de plate-forme et d'étiquette de fournisseur .

Dans Android 11, debugfs ne sont pas accessibles ni montés sur les appareils de production. Les fabricants d'appareils doivent supprimer debugfs .

Tracefs (/sys/kernel/debug/tracing)

Tracefs peut être étiqueté à la fois dans file_contexts et genfscon . Dans Android 7.0, seule la plate-forme étiquette tracefs .

Recommandation : seule la plate-forme peut étiqueter tracefs .

Sysfs (/sys)

Les fichiers dans /sys peuvent être étiquetés en utilisant à la fois file_contexts et genfscon . Dans Android 7.0, la plate-forme et le fournisseur utilisent file_contexts et genfscon pour étiqueter les fichiers dans sysfs .

Recommandation : la plate-forme peut étiqueter les nœuds sysfs qui ne sont pas spécifiques à l'appareil. Sinon, seul le fournisseur peut étiqueter les fichiers.

tmpfs (/dev)

Les fichiers dans /dev peuvent être étiquetés dans file_contexts . Dans Android 7.0, les fichiers d'étiquettes de plate-forme et de fournisseur sont ici.

Recommandation : le fournisseur ne peut étiqueter que les fichiers dans /dev/vendor (par exemple, /dev/vendor/foo , /dev/vendor/socket/bar ).

Rootfs (/)

Les fichiers dans / peuvent être étiquetés dans file_contexts . Dans Android 7.0, les fichiers d'étiquettes de plate-forme et de fournisseur sont ici.

Recommandation : seul le système peut étiqueter les fichiers dans / .

Données (/données)

Les données sont étiquetées via une combinaison de file_contexts et seapp_contexts .

Recommandation : Interdire l'étiquetage des fournisseurs en dehors /data/vendor . Seule la plate-forme peut étiqueter d'autres parties de /data .

Attributs de compatibilité

La politique SELinux est une interaction entre les types source et cible pour des classes d'objets et des autorisations spécifiques. Chaque objet (processus, fichiers, etc.) affecté par la politique SELinux peut avoir un seul type, mais ce type peut avoir plusieurs attributs.

La politique est écrite principalement en termes de types existants :

allow source_type target_type:target_class permission(s);

Cela fonctionne parce que la politique a été écrite avec une connaissance de tous les types. Toutefois, si la stratégie du fournisseur et la stratégie de la plate-forme utilisent des types spécifiques et que l'étiquette d'un objet spécifique ne change que dans l'une de ces stratégies, l'autre peut contenir une stratégie qui a obtenu ou perdu l'accès sur lequel elle s'appuyait auparavant. Par exemple:

File_contexts:
/sys/A   u:object_r:sysfs:s0
Platform: allow p_domain sysfs:class perm;
Vendor: allow v_domain sysfs:class perm;

Peut être changé en :

File_contexts:
/sys/A   u:object_r:sysfs_A:s0

Bien que la politique du fournisseur reste la même, le v_domain perdrait l'accès en raison de l'absence de politique pour le nouveau type sysfs_A .

En définissant une politique en termes d'attributs, nous pouvons donner à l'objet sous-jacent un type qui a un attribut correspondant à la politique pour la plate-forme et le code du fournisseur. Cela peut être fait pour tous les types afin de créer efficacement une politique d'attribut dans laquelle les types concrets ne sont jamais utilisés. En pratique, cela n'est requis que pour les parties de la politique qui se chevauchent entre la plate-forme et le fournisseur, qui sont définies et fournies en tant que politique publique de la plate-forme qui est construite dans le cadre de la politique du fournisseur.

La définition d'une politique publique en tant qu'attributs versionnés répond à deux objectifs de compatibilité de politique :

  • Assurez-vous que le code du fournisseur continue de fonctionner après la mise à jour de la plate-forme . Réalisé en ajoutant des attributs à des types concrets pour les objets correspondant à ceux sur lesquels s'appuyait le code du fournisseur, en préservant l'accès.
  • Capacité à déprécier la stratégie . Réalisé en délimitant clairement les ensembles de règles en attributs qui peuvent être supprimés dès que la version à laquelle ils correspondent n'est plus prise en charge. Le développement peut se poursuivre dans la plate-forme, sachant que l'ancienne politique est toujours présente dans la politique du fournisseur et sera automatiquement supprimée lors de la mise à niveau.

Inscriptibilité de la politique

Pour atteindre l'objectif de ne pas nécessiter la connaissance de modifications de version spécifiques pour le développement de politiques, Android 8.0 inclut un mappage entre les types de politiques publiques de plate-forme et leurs attributs. Le type foo est mappé à l'attribut foo_v N , où N est la version ciblée. vN correspond à la variable de construction PLATFORM_SEPOLICY_VERSION et se présente sous la forme MM.NN , où MM correspond au numéro de SDK de la plate-forme et NN est une version spécifique à la stratégie de plate-forme.

Les attributs de la politique publique ne sont pas versionnés, mais existent plutôt en tant qu'API sur laquelle la plate-forme et la politique du fournisseur peuvent être construites pour maintenir la stabilité de l'interface entre les deux partitions. Les rédacteurs de politique de plate-forme et de fournisseur peuvent continuer à écrire la politique telle qu'elle est écrite aujourd'hui.

Plate-forme-politique publique exportée en tant que allow source_foo target_bar: class perm ; est inclus dans la politique du fournisseur. Lors de la compilation (qui inclut la version correspondante), elle est transformée en la politique qui ira à la partie fournisseur de l'appareil (affichée dans le langage intermédiaire commun (CIL) transformé) :

 (allow source_foo_vN target_bar_vN (class (perm)))

Comme la politique du fournisseur n'est jamais en avance sur la plate-forme, elle ne devrait pas se préoccuper des versions antérieures. Cependant, la politique de la plate-forme devra savoir à quelle date remonte la politique du fournisseur, inclure des attributs à ses types et définir une politique correspondant aux attributs versionnés.

Différences de politique

La création automatique d'attributs en ajoutant _v N à la fin de chaque type ne fait rien sans le mappage des attributs aux types à travers les différences de version. Android maintient un mappage entre les versions pour les attributs et un mappage des types à ces attributs. Cela se fait dans les fichiers de mappage susmentionnés avec des instructions telles que (CIL):

(typeattributeset foo_vN (foo))

Mises à niveau de la plate-forme

La section suivante détaille les scénarios de mise à niveau de plateforme.

Mêmes types

Ce scénario se produit lorsqu'un objet ne modifie pas les étiquettes dans les versions de stratégie. C'est la même chose pour les types source et cible et peut être vu avec /dev/binder , qui est étiqueté binder_device dans toutes les versions. Il est représenté dans la politique transformée comme :

binder_device_v1 … binder_device_vN

Lors de la mise à niveau de v1v2 , la politique de la plate-forme doit contenir :

type binder_device; -> (type binder_device) (in CIL)

Dans le fichier de mappage v1 (CIL) :

(typeattributeset binder_device_v1 (binder_device))

Dans le fichier de mappage v2 (CIL) :

(typeattributeset binder_device_v2 (binder_device))

Dans la politique fournisseur v1 (CIL) :

(typeattribute binder_device_v1)
(allow binder_device_v1 …)

Dans la politique fournisseur v2 (CIL) :

(typeattribute binder_device_v2)
(allow binder_device_v2 …)
Nouveaux types

Ce scénario se produit lorsque la plate-forme a ajouté un nouveau type, ce qui peut se produire lors de l'ajout de nouvelles fonctionnalités ou lors du renforcement de la stratégie.

  • Nouvelle fonctionnalité . Lorsque le type étiquette un objet qui était auparavant inexistant (comme un nouveau processus de service), le code du fournisseur n'interagissait pas directement avec lui auparavant, de sorte qu'aucune stratégie correspondante n'existe. Le nouvel attribut correspondant au type n'a pas d'attribut dans la version précédente et n'aurait donc pas besoin d'une entrée dans le fichier de mappage ciblant cette version.
  • Durcissement politique . Lorsque le type représente le renforcement de la politique, le nouvel attribut de type doit être lié à une chaîne d'attributs correspondant au précédent (similaire à l'exemple précédent en changeant /sys/A de sysfs à sysfs_A ). Le code du fournisseur s'appuie sur une règle permettant l'accès à sysfs et doit inclure cette règle en tant qu'attribut du nouveau type.

Lors de la mise à niveau de v1v2 , la politique de la plate-forme doit contenir :

type sysfs_A; -> (type sysfs_A) (in CIL)
type sysfs; (type sysfs) (in CIL)

Dans le fichier de mappage v1 (CIL) :

(typeattributeset sysfs_v1 (sysfs sysfs_A))

Dans le fichier de mappage v2 (CIL) :

(typeattributeset sysfs_v2 (sysfs))
(typeattributeset sysfs_A_v2 (sysfs_A))

Dans la politique fournisseur v1 (CIL) :

(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

Dans la politique fournisseur v2 (CIL) :

(typeattribute sysfs_A_v2)
(allow … sysfs_A_v2 …)
(typeattribute sysfs_v2)
(allow … sysfs_v2 …)
Types supprimés

Ce scénario (rare) se produit lorsqu'un type est supprimé, ce qui peut arriver lorsque l'objet sous-jacent :

  • Reste mais obtient une étiquette différente.
  • Est supprimé par la plate-forme.

Lors de l'assouplissement de la stratégie, un type est supprimé et l'objet étiqueté avec ce type reçoit une étiquette différente, déjà existante. Cela représente une fusion des mappages d'attributs : le code du fournisseur doit toujours pouvoir accéder à l'objet sous-jacent par l'attribut qu'il possédait auparavant, mais le reste du système doit maintenant pouvoir y accéder avec son nouvel attribut.

Si l'attribut vers lequel il a été basculé est nouveau, alors le réétiquetage est le même que dans le cas du nouveau type, sauf que lorsqu'une étiquette existante est utilisée, l'ajout de l'ancien nouveau type d'attribut entraînerait d'autres objets également étiquetés avec ce type être nouvellement accessible. C'est essentiellement ce qui est fait par la plate-forme et est considéré comme un compromis acceptable pour maintenir la compatibilité.

(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

Exemple de version 1 : réduction des types (suppression de sysfs_A)

Lors de la mise à niveau de v1v2 , la politique de la plate-forme doit contenir :

type sysfs; (type sysfs) (in CIL)

Dans le fichier de mappage v1 (CIL) :

(typeattributeset sysfs_v1 (sysfs))
(type sysfs_A) # in case vendors used the sysfs_A label on objects
(typeattributeset sysfs_A_v1 (sysfs sysfs_A))

Dans le fichier de mappage v2 (CIL) :

(typeattributeset sysfs_v2 (sysfs))

Dans la politique fournisseur v1 (CIL) :

(typeattribute sysfs_A_v1)
(allow … sysfs_A_v1 …)
(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

Dans la politique fournisseur v2 (CIL) :

(typeattribute sysfs_v2)
(allow … sysfs_v2 …)

Exemple Version 2 : Suppression complète (type foo)

Lors de la mise à niveau de v1v2 , la politique de la plate-forme doit contenir :

# nothing - we got rid of the type

Dans le fichier de mappage v1 (CIL) :

(type foo) #needed in case vendors used the foo label on objects
(typeattributeset foo_v1 (foo))

Dans le fichier de mappage v2 (CIL) :

# nothing - get rid of it

Dans la politique fournisseur v1 (CIL) :

(typeattribute foo_v1)
(allow foo …)
(typeattribute sysfs_v1)
(allow sysfs_v1 …)

Dans la politique fournisseur v2 (CIL) :

(typeattribute sysfs_v2)
(allow sysfs_v2 …)
Nouvelle classe/autorisations

Ce scénario se produit lorsqu'une mise à niveau de plate-forme introduit de nouveaux composants de stratégie qui n'existent pas dans les versions précédentes. Par exemple, lorsqu'Android a ajouté le gestionnaire d'objets servicemanager qui a créé les autorisations d'ajout, de recherche et de liste, les démons fournisseur souhaitant s'enregistrer auprès du servicemanager avaient besoin d'autorisations qui n'étaient pas disponibles. Dans Android 8.0, seule la stratégie de plate-forme peut ajouter de nouvelles classes et autorisations.

Pour permettre à tous les domaines qui auraient pu être créés ou étendus par la politique du fournisseur d'utiliser la nouvelle classe sans obstruction, la politique de la plate-forme doit inclure une règle similaire à :

allow {domain -coredomain} *:new_class perm;

Cela peut même nécessiter une politique autorisant l'accès à tous les types d'interface (politique publique), pour s'assurer que l'image du fournisseur obtient l'accès. Si cela se traduit par une politique de sécurité inacceptable (comme cela peut être le cas avec les modifications du gestionnaire de service), une mise à niveau du fournisseur peut potentiellement être forcée.

Classe/autorisations supprimées

Ce scénario se produit lorsqu'un gestionnaire d'objets est supprimé (tel que le gestionnaire d'objets ZygoteConnection ) et ne devrait pas causer de problèmes. La classe et les autorisations du gestionnaire d'objets peuvent rester définies dans la stratégie jusqu'à ce que la version du fournisseur ne l'utilise plus. Cela se fait en ajoutant les définitions au fichier de mappage correspondant.

Personnalisation du fournisseur pour les types nouveaux/réétiquetés

Les nouveaux types de fournisseurs sont au cœur du développement de la politique des fournisseurs, car ils sont nécessaires pour décrire de nouveaux processus, fichiers binaires, périphériques, sous-systèmes et données stockées. En tant que tel, il est impératif d'autoriser la création de types définis par le fournisseur.

Comme la politique du fournisseur est toujours la plus ancienne sur l'appareil, il n'est pas nécessaire de convertir automatiquement tous les types de fournisseur en attributs dans la politique. La plate-forme ne s'appuie sur aucun élément étiqueté dans la politique du fournisseur car la plate-forme n'en a aucune connaissance ; cependant, la plate-forme fournira les attributs et les types publics qu'elle utilise pour interagir avec les objets étiquetés avec ces types (tels que domain , sysfs_type , etc.). Pour que la plateforme continue à interagir correctement avec ces objets, les attributs et les types doivent être correctement appliqués et des règles spécifiques peuvent devoir être ajoutées aux domaines personnalisables (comme init ).

Changements d'attributs pour Android 9

Les appareils mis à niveau vers Android 9 peuvent utiliser les attributs suivants, mais pas les appareils lancés avec Android 9.

Attributs du contrevenant

Android 9 inclut ces attributs liés au domaine :

  • data_between_core_and_vendor_violators . Attribut pour tous les domaines qui enfreignent l'exigence de ne pas partager de fichiers par chemin entre vendor et coredomains . Les processus de plate-forme et de fournisseur ne doivent pas utiliser de fichiers sur disque pour communiquer (ABI instable). Recommandation:
    • Le code du fournisseur doit utiliser /data/vendor .
    • Le système ne doit pas utiliser /data/vendor .
  • system_executes_vendor_violators . Attribut pour tous les domaines système (à l'exception des domaines init et shell domains ) qui violent l'exigence de ne pas exécuter les binaires du fournisseur. L'exécution des binaires du fournisseur a une API instable. La plate-forme ne doit pas exécuter directement les fichiers binaires du fournisseur. Recommandation:
    • De telles dépendances de plate-forme sur les binaires du fournisseur doivent être derrière les HAL HIDL.

      OU

    • coredomains qui ont besoin d'accéder aux fichiers binaires du fournisseur doivent être déplacés vers la partition du fournisseur et donc cesser d'être coredomain .

Attributs non approuvés

Les applications non approuvées qui hébergent du code arbitraire ne devraient pas avoir accès aux services HwBinder, à l'exception de celles considérées comme suffisamment sûres pour l'accès à partir de ces applications (voir les services sécurisés ci-dessous). Les deux raisons principales à cela sont :

  1. Les serveurs HwBinder n'effectuent pas d'authentification client car HIDL n'expose actuellement pas les informations d'UID de l'appelant. Même si HIDL a exposé ces données, de nombreux services HwBinder fonctionnent à un niveau inférieur à celui des applications (telles que les HAL) ou ne doivent pas s'appuyer sur l'identité de l'application pour l'autorisation. Ainsi, pour être sûr, l'hypothèse par défaut est que chaque service HwBinder traite tous ses clients comme étant également autorisés à effectuer les opérations proposées par le service.
  2. Les serveurs HAL (un sous-ensemble de services HwBinder) contiennent du code avec un taux d'incidence de problèmes de sécurité plus élevé que les composants system/core et ont accès aux couches inférieures de la pile (jusqu'au matériel), augmentant ainsi les possibilités de contourner le modèle de sécurité Android. .

Prestations sécurisées

Les services sûrs comprennent :

  • same_process_hwservice . Ces services (par définition) s'exécutent dans le processus du client et ont donc le même accès que le domaine client dans lequel le processus s'exécute.
  • coredomain_hwservice . Ces services ne présentent pas de risques associés à la raison #2.
  • hal_configstore_ISurfaceFlingerConfigs . Ce service est spécifiquement conçu pour être utilisé par n'importe quel domaine.
  • hal_graphics_allocator_hwservice . Ces opérations sont également proposées par le service surfaceflinger Binder, auquel les applications sont autorisées à accéder.
  • hal_omx_hwservice . Il s'agit d'une version HwBinder du service mediacodec Binder, auquel les applications sont autorisées à accéder.
  • hal_codec2_hwservice . Il s'agit d'une version plus récente de hal_omx_hwservice .

Attributs utilisables

Tous hwservices non considérés comme sûrs ont l'attribut untrusted_app_visible_hwservice . Les serveurs HAL correspondants ont l'attribut untrusted_app_visible_halserver . Les appareils lancés avec Android 9 NE DOIVENT PAS utiliser l'un ou l'autre des attributs untrusted .

Recommandation:

  • Les applications non approuvées doivent plutôt parler à un service système qui parle au fournisseur HIDL HAL. Par exemple, les applications peuvent parler à binderservicedomain , puis mediaserver (qui est un binderservicedomain ) à son tour parle à hal_graphics_allocator .

    OU

  • Les applications qui ont besoin d'un accès direct aux HAL vendor doivent avoir leur propre domaine de politique de sécurité défini par le fournisseur.

Tests d'attributs de fichier

Android 9 inclut des tests de temps de construction qui garantissent que tous les fichiers dans des emplacements spécifiques ont les attributs appropriés (par exemple, tous les fichiers dans sysfs ont l'attribut sysfs_type requis).

Plateforme-politique publique

La politique publique de plate-forme est au cœur de la conformité au modèle d'architecture Android 8.0 sans simplement maintenir l'union des politiques de plate-forme de v1 et v2. Les fournisseurs sont exposés à un sous-ensemble de la politique de plate-forme qui contient des types et des attributs utilisables et des règles sur ces types et attributs qui deviennent ensuite partie intégrante de la politique du fournisseur (c'est-à-dire vendor_sepolicy.cil ).

Les types et les règles sont automatiquement traduits dans la politique générée par le fournisseur en attribute_v N de sorte que tous les types fournis par la plate-forme sont des attributs versionnés (cependant, les attributs ne sont pas versionnés). La plate-forme est chargée de mapper les types concrets qu'elle fournit dans les attributs appropriés pour garantir que la politique du fournisseur continue de fonctionner et que les règles fournies pour une version particulière sont incluses. La combinaison de la politique publique de la plate-forme et de la politique du fournisseur satisfait l'objectif du modèle d'architecture Android 8.0 consistant à permettre des versions indépendantes de la plate-forme et du fournisseur.

Mappage aux chaînes d'attributs

Lors de l'utilisation d'attributs pour mapper des versions de stratégie, un type est mappé à un attribut ou à plusieurs attributs, garantissant que les objets étiquetés avec le type sont accessibles via des attributs correspondant à leurs types précédents.

Maintenir l'objectif de masquer les informations de version à l'auteur de la politique signifie générer automatiquement les attributs versionnés et les affecter aux types appropriés. Dans le cas courant des types statiques, c'est simple : type_foo correspond à type_foo_v1 .

Pour un changement d'étiquette d'objet tel que sysfssysfs_A ou mediaserveraudioserver , la création de ce mappage n'est pas triviale (et est décrite dans les exemples ci-dessus). Les responsables de la stratégie de plate-forme doivent déterminer comment créer le mappage aux points de transition pour les objets, ce qui nécessite de comprendre la relation entre les objets et leurs étiquettes attribuées et de déterminer quand cela se produit. Pour la rétrocompatibilité, cette complexité doit être gérée du côté de la plate-forme, qui est la seule partition susceptible d'être uprev.

Mise à jour de la version

Pour plus de simplicité, la plate-forme Android publie une version sepolicy lorsqu'une nouvelle branche de publication est coupée. Comme décrit ci-dessus, le numéro de version est contenu dans PLATFORM_SEPOLICY_VERSION et se présente sous la forme MM.nn , où MM correspond à la valeur SDK et nn est une valeur privée maintenue dans /platform/system/sepolicy. Par exemple, 19.0 pour Kitkat, 21.0 pour Lollipop, 22.0 pour Lollipop-MR1 23.0 pour Marshmallow, 24.0 pour Nougat, 25.0 pour Nougat-MR1, 26.0 pour Oreo, 27.0 pour Oreo-MR1 et 28.0 pour Android 9. toujours des nombres entiers. Par exemple, si un MR bump vers une version nécessite un changement incompatible dans system/sepolicy/public mais pas un bump d'API, alors cette version de sepolicy pourrait être : vN.1 . La version présente dans une branche de développement est une version 10000.0 à ne jamais utiliser dans les appareils d'expédition.

Android peut rendre obsolète la version la plus ancienne lors de la mise à jour. Pour savoir quand abandonner une version, Android peut collecter le nombre d'appareils avec des politiques de fournisseur exécutant cette version d'Android et recevant toujours des mises à jour majeures de la plate-forme. Si le nombre est inférieur à un certain seuil, cette version est obsolète.

Impact sur les performances de plusieurs attributs

Comme décrit dans https://github.com/SELinuxProject/cil/issues/9 , un grand nombre d'attributs affectés à un type entraînent des problèmes de performances en cas d'échec du cache de stratégie.

Cela a été confirmé comme étant un problème dans Android, donc des modifications ont été apportées à Android 8.0 pour supprimer les attributs ajoutés à la stratégie par le compilateur de stratégie, ainsi que pour supprimer les attributs inutilisés. Ces modifications ont résolu les régressions de performances.

System_ext public et politique publique du produit

À partir d'Android 11, les partitions system_ext et produit sont autorisées à exporter leurs types publics désignés vers la partition fournisseur. Comme la politique publique de la plate-forme, le fournisseur utilise des types et des règles automatiquement traduits en attributs versionnés, par exemple de type en type_ N , où N est la version de la plate-forme sur laquelle la partition du fournisseur est construite.

Lorsque les partitions system_ext et product sont basées sur la même version de plate-forme N , le système de construction génère des fichiers de mappage de base vers system_ext/etc/selinux/mapping/ N .cil et product/etc/selinux/mapping/ N .cil , qui contiennent l'identité mappages de type à type_ N . Le fournisseur peut accéder type avec l'attribut versionné type_ N .

Dans le cas où seules les partitions system_ext et produit sont mises à jour, disons N à N+1 (ou plus tard), tandis que le fournisseur reste à N , le fournisseur peut perdre l'accès aux types des partitions system_ext et produit. Pour éviter les ruptures, les partitions system_ext et product doivent fournir des fichiers de mappage de types concrets vers des attributs type_ N . Chaque partenaire est responsable de la maintenance des fichiers de mappage, s'il doit prendre en charge N fournisseur avec N+1 (ou version ultérieure) system_ext et partitions de produit.

Pour ce faire, les partenaires doivent :

  1. Copiez les fichiers de mappage de base générés à partir des partitions N system_ext et produit vers leur arborescence source.
  2. Modifiez les fichiers de mappage si nécessaire.
  3. Installez les fichiers de mappage sur N+1 (ou version ultérieure) system_ext et les partitions de produit.

Par exemple, supposons que N system_ext ait un type public nommé foo_type . Alors system_ext/etc/selinux/mapping/ N .cil dans la partition N system_ext ressemblera à :

(typeattributeset foo_type_N (foo_type))
(expandtypeattribute foo_type_N true)
(typeattribute foo_type_N)

Si bar_type est ajouté à N+1 system_ext, et si bar_type doit être mappé sur foo_type pour N fournisseur, N .cil peut être mis à jour à partir de

(typeattributeset foo_type_N (foo_type))

à

(typeattributeset foo_type_N (foo_type bar_type))

puis installé sur la partition de N+1 system_ext. Le fournisseur N peut continuer à accéder à foo_type et bar_type de N+1 system_ext.

Étiquetage des contextes SELinux

Pour prendre en charge la distinction entre la plate-forme et la stratégie de fournisseur, le système crée des fichiers de contexte SELinux différemment pour les garder séparés.

Contextes de fichiers

Android 8.0 a introduit les changements suivants pour file_contexts :

  • Pour éviter une surcharge de compilation supplémentaire sur le périphérique lors du démarrage, file_contexts cesse d'exister sous la forme binaire. Au lieu de cela, il s'agit de fichiers texte d'expressions régulières lisibles tels que {property, service}_contexts (comme ils l'étaient avant la version 7.0).
  • Les file_contexts sont répartis entre deux fichiers :
    • plat_file_contexts
      • file_context de la plate-forme Android qui n'a pas d'étiquettes spécifiques à l'appareil, à l'exception des parties d'étiquetage de la partition /vendor qui doivent être étiquetées avec précision pour garantir le bon fonctionnement des fichiers sepolicy.
      • Doit résider dans la partition system à /system/etc/selinux/plat_file_contexts sur le périphérique et être chargé par init au début avec le fournisseur file_context .
    • vendor_file_contexts
      • file_context spécifique à l'appareil construit en combinant file_contexts trouvés dans les répertoires pointés par BOARD_SEPOLICY_DIRS dans les fichiers Boardconfig.mk de l'appareil.
      • Doit être installé dans /vendor/etc/selinux/vendor_file_contexts dans la partition vendor et être chargé par init au début avec la plate-forme file_context .

Contextes de propriété

Dans Android 8.0, le property_contexts est partagé entre deux fichiers :

  • plat_property_contexts
    • property_context de la plate-forme Android qui n'a pas d'étiquettes spécifiques à l'appareil.
    • Doit résider dans la partition system à /system/etc/selinux/plat_property_contexts et être chargé par init au début avec le fournisseur property_contexts .
  • vendor_property_contexts
    • property_context spécifique à l'appareil construit en combinant property_contexts trouvés dans les répertoires pointés par BOARD_SEPOLICY_DIRS dans les fichiers Boardconfig.mk de l'appareil.
    • Doit résider dans la partition vendor à /vendor/etc/selinux/vendor_property_contexts et être chargé par init au début avec la plate-forme property_context

Contextes de service

Dans Android 8.0, le service_contexts est réparti entre les fichiers suivants :

  • plat_service_contexts
    • service_context spécifique à la plate-forme Android pour le servicemanager . Le service_context n'a pas d'étiquettes spécifiques à l'appareil.
    • Doit résider dans la partition system à /system/etc/selinux/plat_service_contexts et être chargé par servicemanager au début avec le fournisseur service_contexts .
  • vendor_service_contexts
    • service_context spécifique à l'appareil construit en combinant service_contexts trouvés dans les répertoires pointés par BOARD_SEPOLICY_DIRS dans les fichiers Boardconfig.mk de l'appareil.
    • Doit résider dans la partition vendor à /vendor/etc/selinux/vendor_service_contexts et être chargé par servicemanager au début avec la plate-forme service_contexts .
    • Bien que servicemanager recherche ce fichier au démarrage, pour un périphérique TREBLE entièrement conforme, les vendor_service_contexts NE DOIVENT PAS exister. En effet, toutes les interactions entre les processus vendor et system DOIVENT passer par hwservicemanager / hwbinder .
  • plat_hwservice_contexts
    • Plate-forme Android hwservice_context pour hwservicemanager qui n'a pas d'étiquettes spécifiques à l'appareil.
    • Doit résider dans la partition system à /system/etc/selinux/plat_hwservice_contexts et être chargé par hwservicemanager au début avec le vendor_hwservice_contexts .
  • vendor_hwservice_contexts
    • hwservice_context spécifique à l'appareil construit en combinant hwservice_contexts trouvés dans les répertoires pointés par BOARD_SEPOLICY_DIRS dans les fichiers Boardconfig.mk de l'appareil.
    • Doit résider dans la partition vendor à /vendor/etc/selinux/vendor_hwservice_contexts et être chargé par hwservicemanager au début avec le plat_service_contexts .
  • vndservice_contexts
    • service_context spécifique à l'appareil pour le vndservicemanager construit en combinant vndservice_contexts trouvés dans les répertoires pointés par BOARD_SEPOLICY_DIRS dans le Boardconfig.mk de l'appareil.
    • Ce fichier doit résider dans la partition vendor à /vendor/etc/selinux/vndservice_contexts et être chargé par vndservicemanager au démarrage.

Contextes Seaapp

Dans Android 8.0, le seapp_contexts est divisé en deux fichiers :

  • plat_seapp_contexts
    • Plate-forme Android seapp_context qui n'a pas de modifications spécifiques à l'appareil.
    • Doit résider dans la partition system à /system/etc/selinux/plat_seapp_contexts.
  • vendor_seapp_contexts
    • Extension spécifique à l'appareil de la plate-forme seapp_context construite en combinant seapp_contexts trouvés dans les répertoires pointés par BOARD_SEPOLICY_DIRS dans les fichiers Boardconfig.mk de l'appareil.
    • Doit résider dans la partition vendor à /vendor/etc/selinux/vendor_seapp_contexts .

Autorisations MAC

Dans Android 8.0, le mac_permissions.xml est divisé en deux fichiers :

  • Plate-forme mac_permissions.xml
    • Plate-forme Android mac_permissions.xml qui n'a pas de modifications spécifiques à l'appareil.
    • Doit résider dans la partition system à /system/etc/selinux/.
  • mac_permissions.xml hors plate-forme
    • Extension spécifique à l'appareil de la plate-forme mac_permissions.xml construite à partir de mac_permissions.xml trouvée dans les répertoires pointés par BOARD_SEPOLICY_DIRS dans les fichiers Boardconfig.mk de l'appareil.
    • Doit résider dans la partition vendor dans /vendor/etc/selinux/.