Initialisation du fournisseur

Le processus d'initialisation dispose d'autorisations presque illimitées et utilise des scripts d'entrée des partitions système et fournisseur pour initialiser le système pendant le processus de démarrage. Cet accès provoque un énorme trou dans la répartition système/fournisseur Treble, car les scripts du fournisseur peuvent demander à init d'accéder à des fichiers, des propriétés, etc. qui ne font pas partie de l'interface binaire d'application (ABI) stable du système-fournisseur.

Vendor init est conçu pour combler cette lacune en utilisant un domaine Linux à sécurité renforcée (SELinux) distinct vendor_init pour exécuter les commandes trouvées dans /vendor avec des autorisations spécifiques au fournisseur.

Mécanisme

Le fournisseur init lance un sous-processus d'init au début du processus de démarrage avec le contexte SELinux u:r:vendor_init:s0 . Ce contexte SELinux a considérablement moins d'autorisations que le contexte d'initialisation par défaut et son accès est limité aux fichiers, propriétés, etc. qui sont soit spécifiques au fournisseur, soit faisant partie de l'ABI stable du fournisseur du système.

Init vérifie chaque script qu'il charge pour voir si son chemin commence par /vendor et si tel est le cas, le marque avec une indication que ses commandes doivent être exécutées dans le contexte d'initialisation du fournisseur. Chaque élément intégré d'initialisation est annoté avec un booléen qui spécifie si la commande doit ou non être exécutée dans le sous-processus d'initialisation du fournisseur :

  • La plupart des commandes qui accèdent au système de fichiers sont annotées pour s'exécuter dans le sous-processus d'initialisation du fournisseur et sont donc soumises à la SEPolicy d'initialisation du fournisseur.
  • La plupart des commandes qui ont un impact sur l'état d'initialisation interne (par exemple, le démarrage et l'arrêt des services) sont exécutées dans le cadre du processus d'initialisation normal. Ces commandes sont informées qu'un script du fournisseur les appelle pour effectuer leur propre gestion des autorisations non SELinux.

La boucle de traitement principale d'init contient une vérification selon laquelle si une commande est annotée pour s'exécuter dans le sous-processus du fournisseur et provient d'un script du fournisseur, cette commande est envoyée via la communication inter-processus (IPC) au sous-processus d'initialisation du fournisseur, qui exécute la commande. et renvoie le résultat à init.

Utilisation de l'initialisation du fournisseur

L'initialisation du fournisseur est activée par défaut et ses restrictions s'appliquent à tous les scripts d'initialisation présents dans la partition /vendor . L'initialisation du fournisseur doit être transparente pour les fournisseurs dont les scripts n'accèdent déjà pas uniquement aux fichiers, propriétés, etc. du système.

Cependant, si les commandes d'un script de fournisseur donné violent les restrictions d'initialisation du fournisseur, les commandes échoueront. Les commandes défaillantes ont une ligne dans le journal du noyau (visible avec dmesg) depuis init indiquant l'échec. Un audit SELinux accompagne toute commande défaillante qui a échoué en raison de la politique SELinux. Exemple de panne incluant un audit SELinux :

type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0
init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied

Si une commande échoue, il existe deux options :

  • Si la commande échoue en raison d'une restriction intentionnelle (par exemple si la commande accède à un fichier ou une propriété système), la commande doit être réimplémentée de manière conviviale pour Treble, en passant uniquement par des interfaces stables. Les règles Neverallow empêchent l'ajout d'autorisations pour accéder aux fichiers système qui ne font pas partie de l'ABI stable du fournisseur de système.
  • Si l'étiquette SELinux est nouvelle et ne bénéficie pas déjà d'autorisations dans le système vendor_init.te ni d'autorisations exclues via les règles neverallow, la nouvelle étiquette peut recevoir des autorisations dans le vendor_init.te spécifique au périphérique.

Pour les appareils lancés avant Android 9, les règles Neverallows peuvent être contournées en ajoutant l'attribut de type data_between_core_and_vendor_violators au fichier vendor_init.te spécifique à l'appareil.

Emplacements des codes

L'essentiel de la logique de l'IPC d'initialisation du fournisseur se trouve dans system/core/init/subcontext.cpp .

Le tableau des commandes se trouve dans la classe BuiltinFunctionMap dans system/core/init/builtins.cpp et comprend des annotations qui indiquent si la commande doit être exécutée dans le sous-processus d'initialisation du fournisseur.

La SEPolicy pour l'initialisation du fournisseur est répartie entre les répertoires privé ( system/sepolicy/private/vendor_init.te ) et public ( system/sepolicy/public/vendor_init.te ) dans system/sepolicy.