Microdroid est un mini-OS Android qui s'exécute dans une pVM. Vous n'êtes pas obligé d'utiliser Microdroid. Vous pouvez démarrer une VM avec n'importe quel OS. Toutefois, les principaux cas d'utilisation des VM préemptives ne consistent pas à exécuter un OS autonome, mais plutôt à offrir un environnement d'exécution isolé pour exécuter une partie d'une application avec des garanties de confidentialité et d'intégrité plus solides que celles qu'Android peut fournir.
Avec les systèmes d'exploitation traditionnels, il faut beaucoup de travail (souvent dupliqué) pour assurer une confidentialité et une intégrité solides, car ils ne s'intègrent pas à l'architecture globale d'Android. Par exemple, avec l'architecture Android standard, les développeurs doivent implémenter un moyen de charger et d'exécuter de manière sécurisée une partie de leur application dans la pVM, et la charge utile est conçue pour glibc. L'application Android utilise Bionic, la communication nécessite un protocole personnalisé sur vsock et le débogage à l'aide d'adb est difficile.
Microdroid comble ces lacunes en fournissant une image OS prête à l'emploi, conçue pour nécessiter le moins d'efforts possible de la part des développeurs afin de décharger une partie de leur application dans une pVM. Le code natif est compilé par rapport à Bionic, la communication se fait via Binder, et il permet d'importer des APEX depuis l'hôte Android et expose un sous-ensemble de l'API Android, tel que le keystore pour les opérations de chiffrement avec des clés matérielles. Dans l'ensemble, les développeurs devraient trouver Microdroid comme un environnement familier avec les outils auxquels ils se sont habitués dans l'OS Android complet.
Fonctionnalités
Microdroid est une version allégée d'Android avec quelques composants supplémentaires spécifiques aux pVM. Microdroid est compatible avec :
- Un sous-ensemble d'API NDK (toutes les API pour l'implémentation de libc et Bionic d'Android sont fournies)
- Fonctionnalités de débogage, telles qu'adb, logcat, tombstone et gdb
- Démarrage validé et SELinux
- Chargement et exécution d'un binaire, ainsi que de bibliothèques partagées, intégrés dans un APK
- Binder RPC sur vsock et échange de fichiers avec vérifications d'intégrité implicites
- Chargement des APEX
Microdroid n'est pas compatible avec :
API Java Android dans les packages
android.\*
SystemServer et Zygote
Graphismes/Interface utilisateur
HAL
Architecture Microdroid
Microdroid est semblable à Cuttlefish, car les deux ont une architecture semblable à celle d'Android standard. Microdroid se compose des images de partition suivantes regroupées dans une image disque composite :
bootloader
: valide et démarre le noyau.boot.img
: contient le noyau et le disque RAM d'initialisation.vendor_boot.img
: contient des modules de noyau spécifiques aux VM, tels que virtio.super.img
: se compose de partitions logiques système et fournisseur.vbmeta.img
: contient les métadonnées du démarrage validé.
Les images de partition sont fournies dans le package APEX de virtualisation et sont regroupées dans une image de disque composite par VirtualizationService
. En plus de l'image disque composite de l'OS principal, VirtualizationService
est responsable de la création des partitions suivantes :
payload
: ensemble de partitions soutenues par les APEX et les APK d'Androidinstance
: partition chiffrée permettant de conserver les données de démarrage validées par instance, telles que le sel par instance, les clés publiques APEX de confiance et les compteurs de restauration
Séquence de démarrage
La séquence de démarrage de Microdroid a lieu après le démarrage de l'appareil. Le démarrage de l'appareil est abordé dans la section "Firmware de la VM protégée" du document Architecture. La figure 1 montre les étapes qui se déroulent pendant la séquence de démarrage de Microdroid :
Voici une explication des étapes :
Le bootloader est chargé en mémoire par crosvm et pvmfw commence à s'exécuter. Avant de passer au bootloader, pvmfw effectue deux tâches :
- Vérifie le bootloader pour s'assurer qu'il provient d'une source fiable (Google ou un OEM).
- Garantit que le même bootloader est utilisé de manière cohérente lors de plusieurs démarrages de la même VM protégée grâce à l'image d'instance. Plus précisément, la VM protégée est initialement démarrée avec une image d'instance vide. pvmfw stocke l'identité du bootloader dans l'image d'instance et la chiffre. Ainsi, la prochaine fois que la VM protégée sera démarrée avec la même image d'instance, pvmfw déchiffrera l'identité enregistrée à partir de l'image d'instance et vérifiera qu'il s'agit de la même que celle enregistrée précédemment. Si les identités diffèrent, pvmfw refuse de démarrer.
Le bootloader démarre ensuite Microdroid.
Le bootloader accède au disque de l'instance. Comme pvmfw, le bootloader dispose d'un disque d'instance contenant des informations sur les images de partition utilisées dans cette instance lors des démarrages précédents, y compris la clé publique.
Le bootloader valide vbmeta et les partitions chaînées, telles que
boot
etsuper
, et, si la validation réussit, dérive les secrets de la VM protégée de la phase suivante. Microdroid transmet ensuite le contrôle au noyau.Étant donné que la super partition a déjà été validée par le bootloader (étape 3), le noyau monte la super partition de manière inconditionnelle. Comme pour Android complet, la super partition se compose de plusieurs partitions logiques montées sur dm-verity. Le contrôle est ensuite transmis au processus
init
, qui démarre divers services natifs. Le scriptinit.rc
est semblable à celui d'Android complet, mais adapté aux besoins de Microdroid.Le processus
init
démarre le gestionnaire Microdroid, qui accède à l'image de l'instance. Le service Microdroid Manager déchiffre l'image à l'aide de la clé transmise à l'étape précédente, puis lit les clés publiques et les compteurs de rollback des APK et APEX clients auxquels cette pVM fait confiance. Ces informations sont utilisées ultérieurement parzipfuse
etapexd
lorsqu'ils montent respectivement l'APK client et les APEX demandés.Le service Microdroid Manager démarre
apexd
.apexd
installe les APEX dans les répertoires/apex/<name>
. La seule différence entre la façon dont Android et Microdroid montent les APEX est que dans Microdroid, les fichiers APEX proviennent de périphériques de bloc virtuels (/dev/vdc1
, …), et non de fichiers réguliers (/system/apex/*.apex
).zipfuse
est le système de fichiers FUSE de Microdroid.zipfuse
installe l'APK client, qui est essentiellement un fichier Zip en tant que système de fichiers. En dessous, le fichier APK est transmis en tant que périphérique de bloc virtuel par la pVM avec dm-verity, comme APEX. L'APK contient un fichier de configuration avec une liste d'APEX que le développeur d'applications a demandés pour cette instance pVM. Cette liste est utilisée parapexd
lors de l'activation des APEX.Le flux de démarrage revient au service de gestionnaire Microdroid. Le service de gestion communique ensuite avec
VirtualizationService
d'Android à l'aide de Binder RPC afin de pouvoir signaler des événements importants tels que des plantages ou des arrêts, et accepter des requêtes telles que l'arrêt de la VM protégée. Le service de gestion lit l'emplacement du binaire principal à partir du fichier de configuration de l'APK et l'exécute.
Échange de fichiers (AuthFS)
Il est courant que les composants Android utilisent des fichiers pour les entrées, les sorties et l'état, et qu'ils les transmettent en tant que descripteurs de fichier (type ParcelFileDescriptor
dans AIDL) avec un accès contrôlé par le noyau Android. AuthFS facilite une fonctionnalité similaire pour l'échange de fichiers entre des points de terminaison qui ne se font pas confiance mutuellement au-delà des limites de la pVM.
Fondamentalement, AuthFS est un système de fichiers distant avec des vérifications d'intégrité transparentes sur les opérations d'accès individuelles, semblables à fs-verity
. Les vérifications permettent au frontend, tel qu'un programme de lecture de fichiers exécuté dans une pVM, de détecter si le backend non fiable, généralement Android, a falsifié le contenu du fichier.
Pour échanger des fichiers, le backend (fd\_server
) est démarré avec une configuration par fichier spécifiant s'il est destiné à l'entrée (lecture seule) ou à la sortie (lecture et écriture). Pour l'entrée, le frontend s'assure que le contenu correspond à un hachage connu, en plus d'un arbre de Merkle pour la validation à l'accès. Pour la sortie, AuthFS gère en interne un arbre de hachage du contenu tel qu'il est observé à partir des opérations d'écriture et peut appliquer l'intégrité lorsque les données sont relues.
Le transport sous-jacent est actuellement basé sur Binder RPC, mais cela peut changer à l'avenir pour optimiser les performances.
Gestion des clés
Les pVM sont fournies avec une clé de scellement stable, adaptée à la protection des données persistantes, et une clé d'attestation, adaptée à la production de signatures dont l'origine (pVM) peut être vérifiée.
Binder RPC
La majorité des interfaces d'Android sont exprimées en AIDL, qui est basé sur le pilote du noyau Linux Binder. Pour prendre en charge les interfaces entre les pVM, le protocole Binder a été réécrit pour fonctionner sur des sockets, vsock dans le cas des pVM. Le fonctionnement sur les sockets permet d'utiliser les interfaces AIDL existantes d'Android dans ce nouvel environnement.
Pour configurer la connexion, un point de terminaison, tel que la charge utile pVM, crée un objet RpcServer
, enregistre un objet racine et commence à écouter les nouvelles connexions. Les clients peuvent se connecter à ce serveur à l'aide d'un objet RpcSession
, obtenir l'objet Binder
et l'utiliser exactement comme un objet Binder
est utilisé avec le pilote Binder du noyau.