Mikrodroid

Microdroid to mały system operacyjny Android, który działa w maszynie wirtualnej. Nie musisz używać Microdroid, możesz uruchomić maszynę wirtualną z dowolnym systemem operacyjnym. Jednak główne przypadki użycia dotyczące maszyn wirtualnych nie wymagają uruchamiania samodzielnego systemu operacyjnego, a raczej oferują odizolowane środowisko wykonywania części aplikacji z silniejszymi gwarancjami poufności i integralności niż te, które zapewnia Android.

W przypadku tradycyjnych systemów operacyjnych zapewnienie wysokiego poziomu poufności i integralności wymaga sporo pracy (często powtarzającej się), ponieważ tradycyjne systemy operacyjne nie pasują do ogólnej architektury Androida. Na przykład w przypadku standardowej architektury Androida deweloperzy muszą wdrożyć sposób bezpiecznego wczytywania i wykonywania części aplikacji w pVM, a dane są tworzone 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, udostępniając gotowy obraz systemu operacyjnego, który wymaga od programistów jak najmniejszego wysiłku, aby przekazać część aplikacji do pVM. Kod natywny jest tworzony na podstawie Bionic, komunikacja odbywa się za pomocą Bindera, a interfejs umożliwia importowanie plików APEX z hosta Androida i wyświetla podzbiór interfejsu API Androida, np. repozytorium kluczy do operacji kryptograficznych z kluczami obsługiwanymi przez sprzęt. Deweloperzy powinni uznać Microdroid za znajome środowisko z narzędziami, do których przywykli w ramach pełnego systemu operacyjnego Android.

Funkcje

Microdroid to okrojona wersja Androida z kilkoma dodatkowymi komponentami przeznaczonymi do pVM. Microdroid obsługuje:

  • Podzbiór interfejsów API NDK (udostępniane są wszystkie interfejsy API do implementacji libc i Bionic na Androidzie)
  • Funkcje debugowania, takie jak adb, logcat, tombstone i gd.
  • Weryfikacja podczas uruchamiania i SELinux
  • wczytywanie i wykonywanie binarnych plików z bibliotekami udostępnionymi zawartymi w pliku APK
  • Binder RPC przez vsock i wymiana plików z niejawnymi weryfikacjami integralności
  • Wczytywanie APEX-ów

Microdroid nie obsługuje:

  • interfejsy API na Androida w Javie w pakietach android.\*,

  • SystemServer i Zygote

  • Grafika/UI

  • HAL

Architektura mikrodroida

Microdroid jest podobny do Cuttlefish, ponieważ oba mają architekturę podobną do standardowego Androida. Microdroid składa się z tych partycji: obrazów zgrupowanych w obraz dyskowy:

  • bootloader – weryfikuje i uruchamia jądro.
  • boot.img – zawiera jądro i ramdisk init.
  • vendor_boot.img – zawiera moduły jądra dotyczące maszyn wirtualnych, takie jak virtio.
  • super.img – składa się z partycji logicznych systemu i dostawcy.
  • vbmeta.img – zawiera zweryfikowane metadane rozruchu.

Obrazy partycji są dostarczane w ramach pakietu Virtualization APEX i są zapakowane w obraz złożonego dysku VirtualizationService. Oprócz głównego obrazu złożonego dysku systemu operacyjnego VirtualizationService odpowiada za tworzenie tych partycji:

  • payload – zbiór partycji obsługiwanych przez pliki APEX i pliki APK na Androida;
  • instance – zaszyfrowana partycja do przechowywania danych weryfikacji uruchamiania na poziomie instancji, takich jak sól na poziomie instancji, zaufane klucze publiczne APEX i liczniki cofania

Sekwencja uruchamiania

Sekwencja uruchamiania Microdroid występuje po uruchamianiu urządzenia. Uruchamianie urządzenia jest omawiane w sekcji dotyczącej oprogramowania układowego pVM w dokumencie Architektura. Rysunek 1 przedstawia kroki wykonywane podczas sekwencji uruchamiania Microdroida:

Bezpieczny proces rozruchu instancji microdroid

Rysunek 1. Bezpieczny proces rozruchu instancji microdroid

Oto wyjaśnienie tych kroków:

  1. Program rozruchowy jest ładowany do pamięci przez crosvm, a pvmfw zaczyna się wykonywać. Zanim przejdziesz do bootloadera, pvmfw wykona 2 zadania:

    • Sprawdza program rozruchowy, aby sprawdzić, czy pochodzi on z zaufanego źródła (od Google lub OEM).
    • Zapewnienie spójnego stosowania tego samego bootloadera podczas wielokrotnego uruchamiania tego samego pVM za pomocą obrazu instancji. W szczególności pVM jest uruchamiany z pustym obrazem instancji. pvmfw przechowuje tożsamość bootloadera w obrazie instancji i szyfruje go. Gdy następnym razem uruchomisz maszynę wirtualną z tym samym obrazem instancji, pvmfw odszyfruje zapisaną tożsamość z obrazu instancji i sprawdzi, czy jest to ta sama tożsamość, która została wcześniej zapisana. Jeśli tożsamości się różnią, pvmfw nie uruchamia się.

    Następnie program rozruchowy uruchamia mikrodroida.

  2. Program rozruchowy uzyskuje dostęp do dysku instancji. Podobnie jak w przypadku pvmfw, bootloader ma dysk instancji z informacjami o obrazach partycji używanych w tej instancji podczas poprzednich rozruchów, w tym klucz publiczny.

  3. Program rozruchowy weryfikuje vbmeta i połączone partycje, takie jak bootsuper, a jeśli wszystko się powiedzie, wygeneruje tajne klucze pVM na następnym etapie. Następnie Microdroid przekazuje kontrolę nad jądrem.

  4. Super partycja została już zweryfikowana przez program ładujący (krok 3), więc jądro bezwarunkowo ją montuje. Tak jak w pełnym Androidzie, superpartycja składa się z wielu partycji logicznych podłączonych przez dm-verity. Następnie kontrola jest przekazywana procesowi init, który uruchamia różne usługi natywne. Skrypt init.rc jest podobny do skryptu pełnego Androida, ale został dostosowany do potrzeb mikrodroida.

  5. Proces init uruchamia menedżera Microdroid, który uzyskuje dostęp do obrazu instancji. Usługa menedżera mikrodroidów odszyfrowuje obraz za pomocą klucza przekazanego z poprzedniego etapu i odczytuje klucze publiczne oraz liczniki wycofywania pakietu APK klienta i APEX, którym ufa ta pVM. Te informacje są później używane przez zipfuse i apexd podczas montowania pliku APK klienta i żądanych APEX.

  6. Usługa menedżera Microdroid rozpoczyna się apexd.

  7. apexd montuje APEX-y w katalogach /apex/<name>. Jedyną różnicą między sposobem montowania plików APEX w Androidzie i Microdroid jest to, że w Microdroid pliki APEX pochodzą z wirtualnych urządzeń blokowych (/dev/vdc1, itp.), a nie z zwykłych plików (/system/apex/*.apex).

  8. zipfuse to system plików FUSE Microdroida. zipfuse montuje pakiet APK klienta, który jest w podstawie plikiem Zip jako system plików. Poniżej plik APK jest przekazywany jako urządzenie blokowe przez pVM z dm-verity, tak samo jak w APEX. Plik APK zawiera plik konfiguracji z listą APEX, które zostały zażądane przez dewelopera aplikacji w przypadku tego wystąpienia pVM. Lista jest używana przez apexd podczas aktywowania Apexów.

  9. Proces uruchamiania wraca do usługi menedżera Microdroid. Usługa menedżera komunikuje się następnie z VirtualizationService Androida za pomocą RPC Binder, dzięki czemu może zgłaszać ważne zdarzenia, takie jak awaria czy wyłączenie, oraz akceptować żądania, takie jak zakończenie pVM. Usługa menedżera odczytuje lokalizację głównego binarnego pliku z pliku konfiguracyjnego APK i go wykona.

Wymiana plików (AuthFS)

Komponenty Androida często używają plików do odczytu, zapisu i przechowywania stanu, a także do przekazywania ich jako deskryptorów plików (ParcelFileDescriptor typ w AIDL), których dostęp jest kontrolowany przez jądro Androida. AuthFS umożliwia podobną funkcjonalność do wymiany plików między wzajemnie nieufnymi punktami końcowymi w obrębie granic pVM.

AuthFS to przede wszystkim zdalny system plików z przezroczystymi testami integralności poszczególnych operacji dostępu, podobny do fs-verity. Dzięki tym kontrolom interfejs, np. program do odczytu plików działający w pVM, może wykryć, czy nieufny backend, zwykle Android, nie zmanipulował treści pliku.

Aby można było wymieniać pliki, backend (fd\_server) rozpoczyna od konfiguracji na podstawie pliku, czy jest to dane wejściowe (tylko do odczytu), czy dane wyjściowe (odczyt i zapis). Do wprowadzania danych frontend wymusza zgodność treści ze znanym szyfrem na górze drzewa Merkle w celu weryfikacji podczas dostępu. W przypadku danych wyjściowych AuthFS wewnętrznie utrzymuje drzewo haszowania treści, które jest obserwowane podczas operacji zapisu, i może wymuszać integralność podczas odczytu danych.

Bazowy transport jest obecnie oparty na RPC Binder, ale może się to zmienić w przyszłości, aby zoptymalizować wydajność.

Zarządzanie kluczami

Urządzenia pVM są dostarczane ze stabilnym kluczem pieczętującym, który służy do ochrony danych trwałych, oraz kluczem uwierzytelniającym, który służy do generowania podpisów, które można zweryfikować za pomocą urządzenia pVM.

RPC wiązania

Większość interfejsów Androida jest wyrażana w języku AIDL, który jest oparty na jądrowym sterowniku Bindera. Aby obsługiwać interfejsy między pVM, protokół Binder został przepisany tak, aby działał przez gniazda vsock w przypadku pVM. Praca w gniazdach umożliwia korzystanie w tym nowym środowisku z dotychczasowych interfejsów AIDL Androida.

Aby skonfigurować połączenie, jeden z punktów końcowych, np. ładunek pVM, tworzy obiekt RpcServer, rejestruje obiekt rdzeniowy i rozpoczyna nasłuchiwanie nowych połączeń. Klienty mogą łączyć się z tym serwerem za pomocą obiektu RpcSession, pobierać obiekt Binder i używać go dokładnie tak, jak obiekt Binder używany ze sterownikiem jądra systemu Binder.