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 sont pas l'exécution d'un système d'exploitation autonome, mais plutôt un environnement d'exécution isolé permettant d'exécuter une partie d'une application avec des garanties de confidentialité et d'intégrité plus solides qu'Android.
Avec les systèmes d'exploitation traditionnels, la confidentialité et l'intégrité solides nécessitent une bonne dose de travail (souvent dupliqué) car ils 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é plutôt que 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 Android de libc et Bionic 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 en ce sens que leur architecture est 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
: se compose de partitions logiques du 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 disque composite du système d'exploitation principale, VirtualizationService
est responsable de la création des autres partitions suivantes:
payload
: ensemble de partitions sauvegardées 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 de 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).
- Assurez-vous que le même bootloader est utilisé de manière cohérente sur plusieurs démarrages de la même VM préemptive via l'utilisation de l'image d'instance. Plus précisément, la VM préemptive est initialement démarrée avec une image d'instance vide. pvmfw stocke l'identité du bootloader dans l'image de l'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 lance 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 ultérieurement 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 qu'appareil de stockage de blocs 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 gestionnaire communique ensuite avec le
VirtualizationService
d'Android à l'aide du RPC de liaison pour pouvoir signaler des événements importants tels que le plantage ou l'arrêt, et accepter les 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 offre une fonctionnalité similaire permettant d'échanger des fichiers entre des points de terminaison qui se méfient mutuellement au-delà des limites des VM préemptives.
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
. Ces vérifications permettent à l'interface, telle qu'un programme de lecture de fichiers exécuté dans une VM préemptive, 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 spécifiant s'il est destiné à l'entrée (lecture seule) ou à la sortie (lecture/écriture). Pour l'entrée, l'interface s'assure que le contenu correspond à un hachage connu, au-dessus d'une arborescence Merkle pour la vérification sur accès. Pour la sortie, AuthFS gère en interne une arborescence de hachage des contenus, comme observé lors 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 VM préemptives sont fournies avec une clé de fermeture stable et adaptée à la protection des données persistantes, ainsi qu'une clé d'attestation permettant de produire des signatures produites de manière vérifiable par les VM préemptives.
RPC Binder
La majorité des interfaces Android sont exprimées en AIDL, qui est basé sur le pilote du kernel Linux Binder. Pour accepter les interfaces entre les VM préemptives, le protocole de liaison a été réécrit pour fonctionner sur les sockets (vsock dans le cas des VM préemptives). 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 de liaison du noyau.