Microdroid to mini-Android OS, który działa w pVM. Nie musisz używać Microdroid, możesz uruchomić maszynę wirtualną z dowolnym systemem operacyjnym. Jednak głównymi przypadkami użycia pVM nie są autonomiczne systemy operacyjne, ale raczej izolowane środowisko wykonawcze do uruchamiania części aplikacji z silniejszymi gwarancjami poufności i integralności niż może zapewnić system Android.
W przypadku tradycyjnych systemów operacyjnych zapewnienie silnej poufności i integralności wymaga sporo pracy (często powielanej), ponieważ tradycyjne systemy operacyjne nie pasują do nadrzędnej architektury Androida. Na przykład przy standardowej architekturze Androida programiści muszą zaimplementować sposób bezpiecznego ładowania i wykonywania części swojej aplikacji w pVM, a ładunek jest zbudowany w oparciu o glibc. Aplikacja na Androida korzysta z Bionic, komunikacja wymaga niestandardowego protokołu przez vsock, a debugowanie za pomocą adb jest trudne.
Microdroid wypełnia te luki, dostarczając gotowy obraz systemu operacyjnego zaprojektowany tak, aby wymagał najmniejszego wysiłku od programistów, aby przenieść część ich aplikacji na pVM. Kod natywny jest oparty na Bionic, komunikacja odbywa się przez Binder i umożliwia importowanie APEX z Androida i ujawnia podzbiór Android API, taki jak magazyn kluczy dla operacji kryptograficznych z kluczami sprzętowymi. Ogólnie rzecz biorąc, programiści powinni znaleźć Microdroid jako znajome środowisko z narzędziami, do których przyzwyczaili się w pełnym systemie operacyjnym Android.
Cechy
Microdroid to uproszczona wersja Androida z kilkoma dodatkowymi komponentami specyficznymi dla pVM. Microdroid obsługuje:
- Podzbiór interfejsów API NDK (dostarczono wszystkie interfejsy API dla implementacji libc i Bionic w systemie Android)
- Funkcje debugowania, takie jak adb, logcat, tombstone i gdb
- Zweryfikowany rozruch i włączony SELinux
- Ładowanie i wykonywanie pliku binarnego wraz z bibliotekami współdzielonymi osadzonymi w pakiecie APK
- Binder RPC przez vsock i wymianę plików z niejawnymi kontrolami integralności
- Ładowanie APEX-ów
Microdroid nie obsługuje:
Android Java API w pakietach
android.\*
SystemServer i Zygote
Grafika/UI
HAL
Architektura mikrodroidów
Microdroid jest podobny do Cuttlefish , ponieważ oba mają architekturę podobną do standardowego Androida. Microdroid składa się z następujących obrazów partycji zgrupowanych w złożonym obrazie dysku:
-
bootloader
- Weryfikuje i uruchamia jądro. -
boot.img
— zawiera jądro i init ramdisk. -
vendor\_boot.img
— zawiera moduły jądra specyficzne dla maszyny wirtualnej, takie jak virtio. -
super.img
— składa się z partycji logicznych systemu i dostawcy. -
vbmeta.img
— zawiera zweryfikowane metadane rozruchowe.
Obrazy partycji są dostarczane w Virtualization APEX i są pakowane w kompozytowy obraz dysku przez VirtualizationService
. Oprócz głównego obrazu dysku kompozytowego systemu operacyjnego VirtualizationService
odpowiada za tworzenie tych innych partycji:
-
payload
- zestaw partycji wspierany przez APEX i APK Androida -
instance
— zaszyfrowana partycja do utrwalania zweryfikowanych danych rozruchowych dla instancji, takich jak sól dla instancji, zaufane klucze publiczne APEX i liczniki wycofywania
Sekwencja rozruchowa
Sekwencja rozruchowa Microdroid następuje po rozruchu urządzenia . Rozruch urządzenia jest omówiony w dokumencie Architektura . Rysunek 1 pokazuje kroki, które mają miejsce podczas sekwencji rozruchowej Microdroid:
Oto wyjaśnienie kroków:
Bootloader jest ładowany do pamięci przez crossvm i zaczyna działać pvmfw. Przed przejściem do bootloadera pvmfw wykonuje dwa zadania:
- Weryfikuje bootloader, aby sprawdzić, czy pochodzi z zaufanego źródła (Google lub OEM).
- Zapewnia, że ten sam program ładujący jest konsekwentnie używany w wielu rozruchach tej samej pVM dzięki użyciu obrazu instancji. W szczególności pVM jest początkowo uruchamiany z pustym obrazem instancji. pvmfw przechowuje tożsamość programu ładującego w obrazie instancji i szyfruje go. Tak więc następnym razem, gdy pVM zostanie uruchomiony z tym samym obrazem instancji, pvmfw odszyfruje zapisaną tożsamość z obrazu instancji i weryfikuje, czy jest to ten sam, który został wcześniej zapisany. Jeśli tożsamości różnią się, pvmfw odmawia uruchomienia.
Następnie bootloader uruchamia Microdroid.
Bootloader uzyskuje dostęp do dysku instancji. Podobnie jak pvmfw, bootloader ma dysk z instancją z informacjami o obrazach partycji użytych w tej instancji podczas poprzednich rozruchów, w tym o kluczu publicznym.
Bootloader weryfikuje vbmeta i powiązane partycje, takie jak
boot
isuper
, a jeśli się powiedzie, wyprowadza sekrety pVM następnego etapu. Następnie Microdroid przekazuje kontrolę jądru.Ponieważ superpartycja została już zweryfikowana przez bootloader (krok 3), jądro bezwarunkowo montuje superpartycję. Podobnie jak w przypadku pełnego Androida, superpartycja składa się z wielu partycji logicznych zamontowanych przez dm-verity. Kontrola jest następnie przekazywana do procesu
init
, który uruchamia różne usługi natywne. Skryptinit.rc
jest podobny do pełnego Androida, ale dostosowany do potrzeb Microdroid.Proces
init
uruchamia menedżera Microdroid, który uzyskuje dostęp do obrazu instancji. Usługa menedżera Microdroid odszyfrowuje obraz przy użyciu klucza przekazanego z poprzedniego etapu i odczytuje klucze publiczne oraz liczniki wycofywania pakietu APK i APEX klienta, którym ufa ta pVM. Te informacje są później używane przezzipfuse
iapexd
, gdy odpowiednio montują plik APK klienta i żądają APEX-ów.Usługa menedżera Microdroid uruchamia się
apexd
.apexd
montuje APEX w katalogach/apex/<name>
. Jedyną różnicą między tym, jak Android i Microdroid mounta APEX jest to, że w Microdroid pliki APEX pochodzą z wirtualnych urządzeń blokowych (/dev/vdc1
, …), a nie ze zwykłych plików (/system/apex/*.apex
).zipfuse
to system plików FUSE firmy Microdroid.zipfuse
montuje pakiet APK klienta, który jest zasadniczo plikiem Zip jako systemem plików. Poniżej plik APK jest przekazywany jako wirtualne urządzenie blokowe przez pVM z dm-verity, tak samo jak APEX. Pakiet APK zawiera plik konfiguracyjny z listą plików APEX, o które poprosił deweloper aplikacji dla tej instancji pVM. Lista jest używana przezapexd
podczas aktywacji APEX-ów.Przepływ rozruchowy powraca do usługi menedżera Microdroid. Usługa menedżera komunikuje się następnie z usługą
VirtualizationService
systemu Android za pomocą Binder RPC, dzięki czemu może zgłaszać ważne zdarzenia, takie jak awaria lub zamknięcie, i akceptować żądania, takie jak zakończenie działania pVM. Usługa menedżera odczytuje lokalizację głównego pliku binarnego z pliku konfiguracyjnego APK i wykonuje go.
Wymiana plików (AuthFS)
Komponenty systemu Android często używają plików jako danych wejściowych, wyjściowych i stanu oraz przekazują je jako deskryptory plików (typ ParcelFileDescriptor
w AIDL) z dostępem kontrolowanym przez jądro systemu Android. AuthFS ułatwia podobną funkcjonalność wymiany plików między wzajemnie nieufnymi punktami końcowymi w granicach pVM.
Zasadniczo AuthFS jest zdalnym systemem plików z przejrzystymi kontrolami integralności poszczególnych operacji dostępu, podobnym do fs-verity
. Kontrole pozwalają frontendowi, takiemu jak program do odczytu plików działający w pVM, wykryć, czy niezaufany backend, zwykle Android, ingerował w zawartość pliku.
Aby wymieniać pliki, backend ( fd\_server
) jest uruchamiany z konfiguracją na plik określającą, czy jest przeznaczony do wprowadzania (tylko do odczytu), czy do wyjścia (odczyt-zapis). W przypadku danych wejściowych frontend wymusza, aby zawartość była zgodna ze znanym hashem, znajdującym się na szczycie drzewa Merkle w celu weryfikacji przy dostępie. W przypadku danych wyjściowych AuthFS wewnętrznie utrzymuje drzewo skrótu zawartości obserwowane z operacji zapisu i może wymusić integralność podczas odczytu danych.
Transport bazowy jest obecnie oparty na Binder RPC, jednak może się to zmienić w przyszłości, aby zoptymalizować wydajność.
Zarządzanie kluczami
Maszyny pVM są dostarczane ze stabilnym kluczem uszczelniającym, który jest odpowiedni dla chronionych trwałych danych, oraz kluczem atestacyjnym, który nadaje się do tworzenia podpisów, które są weryfikowalne przez pVM.
RPC spoiwa
Większość interfejsów Androida jest wyrażona w AIDL , który jest zbudowany na sterowniku jądra Binder Linux. Aby obsługiwać interfejsy między pVM, protokół Binder został przepisany do pracy przez gniazda, vsock w przypadku pVM. Działanie przez gniazda umożliwia korzystanie z istniejących interfejsów AIDL systemu Android w tym nowym środowisku.
Aby skonfigurować połączenie, jeden punkt końcowy, taki jak ładunek pVM, tworzy obiekt RpcServer
, rejestruje obiekt główny i rozpoczyna nasłuchiwanie nowych połączeń. Klienci mogą łączyć się z tym serwerem za pomocą obiektu RpcSession
, pobierać obiekt Binder
i używać go dokładnie tak, jak obiekt Binder
jest używany ze sterownikiem jądra Binder.