Compatibilité des politiques

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

La conception de la politique SELinux basée sur les triples considère 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 .

Sous Android 8.0 et versions ultérieures, la politique globale de SELinux est divisée en composants privés et publics. Les composants publics comprennent la stratégie et l’infrastructure associée, dont la disponibilité est garantie pour une version de plateforme. Cette stratégie sera exposée aux rédacteurs de stratégie du fournisseur pour permettre à ces derniers de créer un fichier de stratégie du fournisseur qui, combiné à la stratégie fournie par la plateforme, aboutira à une stratégie entièrement fonctionnelle pour un appareil.

  • Pour le versioning, la politique publique de plateforme exportée sera écrite sous forme d'attributs .
  • Pour faciliter la rédaction des politiques, les types exportés seront transformés en attributs versionnés dans le cadre du processus de création de politiques. 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 les objets sont étiquetés avec un type, cela ne rompt pas le comportement garanti par la politique publique de plateforme dans une version précédente. Ce mappage est maintenu à jour en gardant à jour un fichier de mappage pour chaque version de la plateforme , qui conserve les informations d'appartenance aux attributs pour chaque type exporté dans la politique publique.

Propriété et étiquetage des objets

Lors de la personnalisation de la stratégie dans Android 8.0 et versions ultérieures, la propriété doit être clairement définie pour chaque objet afin de séparer la stratégie de la plate-forme et celle du fournisseur. Par exemple, si le fournisseur étiquette /dev/foo et que la plateforme étiquette ensuite /dev/foo dans une OTA ultérieure, le comportement sera 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 à la dernière étiquette appliquée. 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 être interrompus car le mauvais nœud de périphérique a été créé.

Les propriétés du système ont également le potentiel de nommer des collisions 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 possédant une étiquette SELinux, notamment 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 types/attributs SELinux peuvent également entrer en collision. Une collision de 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 compilation d’une stratégie comportant des déclarations en double échouera. Pour éviter les collisions de types et de noms d'attributs, toutes les déclarations des fournisseurs 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

Il est préférable d'éviter les collisions d'étiquetage en utilisant les espaces de noms de propriétés. Pour identifier facilement les propriétés de la plateforme et éviter les conflits de noms lors du renommage ou de l'ajout de propriétés de plateforme exportées, assurez-vous que toutes les propriétés du 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 vient 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 de fichiers est un défi car les politiques de la plate-forme et du fournisseur fournissent généralement des étiquettes pour tous les systèmes de fichiers. Contrairement à la dénomination de type, l'espacement des noms des fichiers n'est pas pratique puisque beaucoup 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.

Fournisseur (/fournisseur)

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 communiquer et/ou accéder à des parties de la partition vendor . Exemples:

/vendor Étiquette fournie par la plateforme Processus de 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 l'étiquette par défaut pour tous les fichiers de la partition vendor . La politique de la plate-forme l’exige pour accéder aux implémentations passthrough HAL.
  • Tous les nouveaux exec_types ajoutés dans la partition vendor via SEPolicy du fournisseur doivent avoir l'attribut vendor_file_type . Ceci est appliqué via neverallows.
  • Pour éviter les conflits avec les futures mises à jour de la plate-forme/du framework, évitez d'étiqueter les fichiers autres que exec_types dans la partition vendor .
  • Toutes les dépendances de bibliothèque pour les HAL de même 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 politique de la plate-forme et celle du fournisseur utilisaient genfscon pour étiqueter les fichiers dans procfs .

Recommandation : uniquement les étiquettes de stratégie de plateforme /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 politique 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 s'adapter aux futures interfaces du noyau exposées via procfs et de les étiqueter explicitement selon les besoins.

Débogages (/sys/kernel/debug)

Debugfs peuvent être étiquetés à la fois dans file_contexts et genfscon . Dans Android 7.0 à Android 10, les étiquettes de plate-forme et de fournisseur debugfs .

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 peuvent être étiquetées à la fois dans file_contexts et genfscon . Sous Android 7.0, seule la plateforme étiquette tracefs .

Recommandation : Seule la plateforme 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 à un périphérique. 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 peut étiqueter uniquement les fichiers dans /dev/vendor (par exemple, /dev/vendor/foo , /dev/vendor/socket/bar ).

Racines (/)

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 ne peut avoir qu'un seul type, mais ce type peut avoir plusieurs attributs.

La politique est rédigée principalement en termes de types existants :

allow source_type target_type:target_class permission(s);

Cela fonctionne parce que la politique a été rédigée avec des connaissances de tous types. Toutefois, si la stratégie du fournisseur et la stratégie de la plateforme utilisent des types spécifiques et que l'étiquette d'un objet spécifique change dans une seule de ces stratégies, l'autre peut contenir une stratégie qui a obtenu ou perdu l'accès sur lequel on 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;

Pourrait être modifié 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 possède un attribut correspondant à la politique à la fois 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 plate-forme 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é des politiques :

  • Assurez-vous que le code du fournisseur continue de fonctionner après la mise à jour de la plateforme . Obtenu en ajoutant des attributs à des types concrets pour les objets correspondant à ceux sur lesquels reposait le code du fournisseur, en préservant l'accès.
  • Possibilité de déprécier la politique . Ceci est obtenu 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 continuer sur la plateforme, sachant que l'ancienne politique est toujours présente dans la politique du fournisseur et sera automatiquement supprimée lors de la mise à niveau.

Écriture des règles

Pour atteindre l'objectif de ne pas exiger la connaissance de changements de version spécifiques pour l'élaboration 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 est de la forme MM.NN , où MM correspond au numéro SDK de la plateforme et NN est une version spécifique à la stratégie de plateforme.

Les attributs de la politique publique ne sont pas versionnés, mais existent plutôt en tant qu'API sur laquelle la politique de la plate-forme et du fournisseur peut s'appuyer pour maintenir la stabilité de l'interface entre les deux partitions. Les rédacteurs de politiques de plate-forme et de fournisseur peuvent continuer à rédiger des politiques telles qu’elles sont rédigées aujourd’hui.

Politique publique de plate-forme exportée sous la allow source_foo target_bar: class perm ; est inclus dans le cadre de la politique du fournisseur. Lors de la compilation (qui inclut la version correspondante), elle est transformée en politique qui ira à la partie fournisseur de l'appareil (affichée dans le Common Intermediate Language (CIL) transformé) :

 (allow source_foo_vN target_bar_vN (class (perm)))

Comme la politique des fournisseurs n’est jamais en avance sur la plateforme, elle ne doit pas se préoccuper des versions antérieures. Cependant, la politique de la plate-forme devra connaître l'ancienneté de 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 mapper les attributs aux types à travers les différences de version. Android maintient un mappage entre les versions pour les attributs et un mappage des types avec 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 plateforme

La section suivante détaille les scénarios de mise à niveau de la 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. Elle est représentée dans la politique transformée comme suit :

binder_device_v1 … binder_device_vN

Lors de la mise à niveau de v1v2 , la politique de plateforme 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 du fournisseur v1 (CIL) :

(typeattribute binder_device_v1)
(allow binder_device_v1 …)

Dans la politique du fournisseur v2 (CIL) :

(typeattribute binder_device_v2)
(allow binder_device_v2 …)
Nouveaux types

Ce scénario se produit lorsque la plateforme a ajouté un nouveau type, ce qui peut se produire lors de l'ajout de nouvelles fonctionnalités ou lors du renforcement des politiques.

  • Nouvelle fonctionnalité . Lorsque le type étiquette un objet qui était auparavant inexistant (comme un nouveau processus de service), le code du fournisseur n'a pas interagi directement avec lui auparavant, donc 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 des politiques . Lorsque le type représente un 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 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 plateforme 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 du fournisseur v1 (CIL) :

(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

Dans la politique du 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 se produire lorsque l'objet sous-jacent :

  • Reste mais reçoit une étiquette différente.
  • Est supprimé par la plateforme.

Lors de l'assouplissement de la politique, 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 de mappages d'attributs : le code du fournisseur doit toujours pouvoir accéder à l'objet sous-jacent par l'attribut qu'il possédait, mais le reste du système doit désormais 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 attribut nouveau type entraînerait que d'autres objets soient également étiquetés avec ce type. être nouvellement accessible. C’est essentiellement ce que fait la plateforme 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 plateforme 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 du fournisseur v1 (CIL) :

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

Dans la politique du fournisseur v2 (CIL) :

(typeattribute sysfs_v2)
(allow … sysfs_v2 …)

Exemple de version 2 : suppression complète (type foo)

Lors de la mise à niveau de v1v2 , la politique de plateforme 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 du fournisseur v1 (CIL) :

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

Dans la politique du fournisseur v2 (CIL) :

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

Ce scénario se produit lorsqu'une mise à niveau de plateforme introduit de nouveaux composants de stratégie qui n'existent pas dans les versions précédentes. Par exemple, lorsque Android a ajouté le gestionnaire d'objets servicemanager qui a créé les autorisations d'ajout, de recherche et de liste, les démons fournisseurs souhaitant s'enregistrer auprès du servicemanager avaient besoin d'autorisations qui n'étaient pas disponibles. Sous 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 plateforme 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 garantir l'accès à l'image du fournisseur. Si cela entraîne une politique de sécurité inacceptable (comme cela peut être le cas avec les modifications apportées au gestionnaire de services), une mise à niveau du fournisseur pourrait 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 poser de problèmes. La classe du gestionnaire d'objets et les autorisations peuvent rester définies dans la stratégie jusqu'à ce que la version du fournisseur ne les 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 des politiques des fournisseurs, car ils sont nécessaires pour décrire les nouveaux processus, binaires, appareils, 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 stratégie 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 stratégie. La plateforme ne s'appuie sur rien de ce qui est étiqueté dans la politique du fournisseur, car elle n'en a aucune connaissance ; cependant, la plateforme 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 d'interagir correctement avec ces objets, les attributs et les types doivent être appliqués de manière appropriée et des règles spécifiques peuvent devoir être ajoutées aux domaines personnalisables (tels que init ).

Modifications 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 violent l'exigence de ne pas partager de fichiers par chemin entre vendor et coredomains . Les processus de la plate-forme et du 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 plateforme ne doit pas exécuter directement les binaires du fournisseur. Recommandation:
    • De telles dépendances de plate-forme sur les binaires des fournisseurs doivent être derrière les HAL HIDL.

      OU

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

Attributs non fiables

Les applications non fiables 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 y accéder à partir de ces applications (voir les services sécurisés ci-dessous). Les deux principales raisons à cela sont :

  1. Les serveurs HwBinder n'effectuent pas d'authentification client car HIDL n'expose actuellement pas les informations UID de l'appelant. Même si HIDL exposait 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 des 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. .

Services sécurisés

Les services sécurisés 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 n°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, à laquelle 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 aucun des attributs untrusted .

Recommandation:

  • Les applications non fiables devraient plutôt communiquer avec un service système qui communique avec le fournisseur HIDL HAL. Par exemple, les applications peuvent communiquer avec binderservicedomain , puis mediaserver (qui est un binderservicedomain ) parle à son tour avec hal_graphics_allocator .

    OU

  • Les applications qui nécessitent un accès direct aux HAL vendor doivent disposer de leur propre domaine de stratégie défini par le fournisseur.

Tests d'attributs de fichiers

Android 9 inclut des tests de temps de construction qui garantissent que tous les fichiers situés dans des emplacements spécifiques disposent des attributs appropriés (par exemple, tous les fichiers de 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 des v1 et v2. Les fournisseurs sont exposés à un sous-ensemble de politique de plate-forme qui contient des types et attributs utilisables ainsi que 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 stratégie générée par le fournisseur attribute_v N de sorte que tous les types fournis par la plateforme soient des attributs versionnés (cependant, les attributs ne sont pas versionnés). La plateforme 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 plate-forme et de la politique du fournisseur répond à l'objectif du modèle d'architecture Android 8.0 consistant à permettre des constructions indépendantes de plate-forme et de fournisseur.

Mappage avec des chaînes d'attributs

Lorsque vous utilisez des attributs pour mapper des versions de stratégie, un type est mappé à un ou plusieurs attributs, garantissant ainsi que les objets étiquetés avec le type sont accessibles via les attributs correspondant à leurs types précédents.

Maintenir l'objectif de masquer les informations de version à l'auteur de la stratégie signifie générer automatiquement les attributs versionnés et les attribuer 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 des politiques de plateforme 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 les étiquettes qui leur sont attribuées et de déterminer quand cela se produit. Pour des raisons de compatibilité ascendante, cette complexité doit être gérée du côté de la plate-forme, qui est la seule partition pouvant évoluer.

Versions améliorées

Pour plus de simplicité, la plate-forme Android publie une version sepolicy lorsqu'une nouvelle branche de version est supprimée. Comme décrit ci-dessus, le numéro de version est contenu dans PLATFORM_SEPOLICY_VERSION et est de la forme MM.nn , où MM correspond à la valeur du SDK et nn est une valeur privée conservée 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. Les Uprevs ne sont pas toujours des nombres entiers. Par exemple, si une modification MR vers une version nécessite une modification incompatible dans system/sepolicy/public mais pas une modification de l'API, alors cette version de la stratégie pourrait être : vN.1 . La version présente dans une branche de développement est une version à ne jamais utiliser dans les appareils d'expédition 10000.0 .

Android peut rendre obsolète la version la plus ancienne lors de la mise à jour. Pour savoir quand rendre obsolète une version, Android peut collecter le nombre d'appareils dotés de 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 attribué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, des modifications ont donc é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 changements ont résolu les régressions de performances.

Politique publique System_ext et politique publique du produit

À partir d'Android 11, les partitions system_ext et product sont autorisées à exporter leurs types publics désignés vers la partition du 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 build 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 du type au type_ N . Le fournisseur peut accéder type avec l'attribut versionné type_ N .

Dans le cas où seules les partitions system_ext et product sont mises à jour, disons N à N+1 (ou plus tard), alors que le fournisseur reste à N , le fournisseur peut perdre l'accès aux types de partitions system_ext et product. Pour éviter toute casse, les partitions system_ext et product doivent fournir des fichiers de mappage des types concrets vers les attributs type_ N . Chaque partenaire est responsable de la maintenance des fichiers de mappage, s'il doit prendre en charge N fournisseurs 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 de N system_ext et des partitions de produit vers leur arborescence source.
  2. Modifiez les fichiers de mappage si nécessaire.
  3. Installez les fichiers de mappage sur les partitions system_ext et produit N+1 (ou version ultérieure).

Par exemple, supposons que N system_ext ait un type public nommé foo_type . Ensuite, 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é à foo_type pour le fournisseur N , 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 N+1 system_ext. Le fournisseur N peut continuer à accéder aux foo_type et bar_type de N+1 system_ext.

Étiquetage des contextes SELinux

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

Contextes de fichiers

Android 8.0 a introduit les modifications suivantes pour file_contexts :

  • Pour éviter une surcharge de compilation supplémentaire sur le périphérique lors du démarrage, file_contexts cessent d'exister sous la forme binaire. Au lieu de cela, il s'agit de fichiers texte d'expression régulière 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 au périphérique, à l'exception de l'étiquetage des parties de la partition /vendor qui doivent être étiquetées avec précision pour garantir le bon fonctionnement des fichiers de stratégie.
      • 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é sur /vendor/etc/selinux/vendor_file_contexts dans la partition vendor et être chargé par init au démarrage avec la plateforme file_context .

Contextes de propriété

Dans Android 8.0, le property_contexts est réparti 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 sous /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 dans /vendor/etc/selinux/vendor_property_contexts et être chargé par init au début avec la plateforme property_context

Contextes de services

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 sous /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 dans /vendor/etc/selinux/vendor_service_contexts et être chargé par servicemanager au début avec la plateforme service_contexts .
    • Bien que servicemanager recherche ce fichier au moment du 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
    • Plateforme Android hwservice_context pour hwservicemanager qui n'a pas d'étiquettes spécifiques à l'appareil.
    • Doit résider dans la partition system sous /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 au périphérique construit en combinant hwservice_contexts trouvés dans les répertoires pointés par BOARD_SEPOLICY_DIRS dans les fichiers Boardconfig.mk du périphérique.
    • Doit résider dans la partition vendor dans /vendor/etc/selinux/vendor_hwservice_contexts et être chargé par hwservicemanager au début avec 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 dans /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 ne comporte aucune modification spécifique à l'appareil.
    • Doit résider dans la partition system à l' /system/etc/selinux/plat_seapp_contexts.
  • vendor_seapp_contexts
    • Extension spécifique à l'appareil à 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 à l' /vendor/etc/selinux/vendor_seapp_contexts .

Autorisations MAC

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

  • Plateforme mac_permissions.xml
    • Plateforme Android mac_permissions.xml qui ne comporte aucune modification spécifique à l'appareil.
    • Doit résider dans la partition system à l' /system/etc/selinux/.
  • Non-plateforme mac_permissions.xml
    • 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 à l' /vendor/etc/selinux/.