Microdroid est un mini-OS Android qui s'exécute dans une pVM. Vous n'avez pas besoin 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 à proposer un environnement d'exécution isolé pour exécuter une partie d'une application avec des garanties de confidentialité et d'intégrité plus strictes qu'Android ne peut fournir.
Avec les systèmes d'exploitation traditionnels, la confidentialité et l'intégrité solides nécessitent un travail considérable (souvent dupliqué), car les systèmes d'exploitation traditionnels ne correspondent pas à l'architecture Android globale. 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. La charge utile est compilée avec 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 d'OS prête à l'emploi conçue pour que les développeurs n'aient pas à déployer beaucoup d'efforts pour transférer une partie de leur application vers une pVM. Le code natif est compilé avec Bionic. La communication s'effectue via Binder. Il permet d'importer des APEX à partir de l'Android hôte et expose un sous-ensemble de l'API Android, comme le keystore pour les opérations cryptographiques 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 les éléments suivants:
- Un sous-ensemble d'API NDK (toutes les API pour l'implémentation de libc et de Bionic sur Android sont fournies)
- Fonctionnalités de débogage, telles que 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 à un APK
- RPC de liaison via vsock et échange de fichiers avec des 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 de disque composite:
bootloader
: vérifie et démarre le noyau.boot.img
: contient le noyau et le ramdisk d'initialisation.vendor_boot.img
: contient des modules de noyau spécifiques aux VM, tels que virtio.super.img
: consiste en des partitions logiques système et du fournisseur.vbmeta.img
: contient les métadonnées de démarrage validé.
Les images de partition sont fournies dans l'APEX de virtualisation et sont empaquetées dans une image de disque composite par VirtualizationService
. En plus de l'image de disque composite principale de l'OS, VirtualizationService
est chargé de créer ces autres partitions:
payload
: ensemble de partitions prises en charge par les APEX et les APK d'Androidinstance
: partition chiffrée pour la persistance des données de démarrage validées par instance, telles que le sel par instance, les clés publiques APEX approuvées et les compteurs de rollback
Séquence de démarrage
La séquence de démarrage Microdroid se produit après le démarrage de l'appareil. Le démarrage de l'appareil est abordé dans la section "Micrologiciel pVM" 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 à suivre:
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 vérifier s'il provient d'une source fiable (Google ou un OEM).
- Assure que le même bootloader est utilisé de manière cohérente lors de plusieurs démarrages de la même pVM via l'image d'instance. Plus précisément, la pVM 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. Par conséquent, la prochaine fois que la pVM 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 identité que celle précédemment enregistrée. 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 vérifie vbmeta et les partitions en chaîne, telles que
boot
etsuper
, et, en cas de réussite, dérive les secrets de pVM de l'étape suivante. Microdroid cède ensuite le contrôle au kernel.Étant donné que la super partition a déjà été validée par le bootloader (étape 3), le noyau monte la super partition sans condition. 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 de gestion Microdroid déchiffre l'image à l'aide de la clé transmise à l'étape précédente et lit les clés publiques et les compteurs de rollback de l'APK client et des APEX auxquels cette pVM fait confiance. Ces informations sont utilisées plus tard parzipfuse
etapexd
lorsqu'ils montent l'APK client et les APEX demandés, respectivement.Le service de gestion Microdroid 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
, etc.), et non de fichiers standards (/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 dispositif de bloc virtuel par la pVM avec dm-verity, comme pour APEX. L'APK contient un fichier de configuration avec une liste des APEX que le développeur de l'application a demandés pour cette instance de pVM. La liste est utilisée parapexd
lors de l'activation des APEX.Le flux de démarrage revient au service de gestion Microdroid. Le service de gestion communique ensuite avec
VirtualizationService
d'Android à l'aide de RPC Binder afin de pouvoir signaler des événements importants tels que les plantages ou les arrêts, et d'accepter des requêtes telles que l'arrêt de la pVM. 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 l'entrée, la sortie et l'état, et les transmettent en tant que descripteurs de fichiers (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 mutuellement méfiants au-delà des limites des 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, semblable à 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 approuvé, 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 indiquant s'il est destiné à l'entrée (lecture seule) ou à la sortie (lecture-écriture). Pour l'entrée, le frontend s'assure que le contenu correspond à un hachage connu, au-dessus d'un arbre 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 lues.
Le transport sous-jacent est actuellement basé sur le RPC Binder, mais cela pourrait 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 vérifiables par la pVM.
RPC Binder
La majorité des interfaces Android sont exprimées en AIDL, qui est basé sur le pilote du kernel 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 des 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 de 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 du kernel Binder.