Микродроид

Microdroid — это мини-версия ОС Android, работающая в виртуальной машине (pVM). Использовать Microdroid не обязательно, можно запустить виртуальную машину с любой ОС. Однако pVM в основном используются не для запуска отдельной ОС, а для предоставления изолированной среды выполнения для запуска части приложения с более высокими гарантиями конфиденциальности и целостности, чем Android.

В традиционных операционных системах обеспечение высокой конфиденциальности и целостности данных требует значительного объёма работы (часто дублирующейся), поскольку традиционные операционные системы не соответствуют общей архитектуре Android. Например, в стандартной архитектуре Android разработчикам необходимо реализовать средства безопасной загрузки и выполнения части своего приложения в pVM, а полезная нагрузка построена на основе glibc. Приложение для Android использует Bionic, для взаимодействия требуется собственный протокол через vsock, а отладка с помощью adb затруднена.

Microdroid заполняет эти пробелы, предоставляя готовый образ ОС, разработанный таким образом, чтобы разработчикам было проще выгрузить часть своего приложения в виртуальную машину (pVM). Нативный код написан на Bionic, взаимодействие осуществляется через Binder, и он позволяет импортировать APEX-файлы с хост-системы Android и предоставляет подмножество API Android, например, хранилище ключей для криптографических операций с аппаратными ключами. В целом, Microdroid должен стать для разработчиков знакомой средой с инструментами, к которым они привыкли в полноценной ОС Android.

Функции

Microdroid — это урезанная версия Android с несколькими дополнительными компонентами, специфичными для pVM. Microdroid поддерживает:

  • Подмножество API NDK (предоставлены все API для реализации libc и Bionic в Android)
  • Функции отладки, такие как adb, logcat, tombstone и gdb
  • Проверенная загрузка и SELinux
  • Загрузка и выполнение двоичного файла вместе с общими библиотеками, встроенными в APK
  • Binder RPC через vsock и обмен файлами с неявными проверками целостности
  • Загрузка APEX

Microdroid не поддерживает:

  • API-интерфейсы Android Java в пакетах android.\*

  • SystemServer и Zygote

  • Графика/пользовательский интерфейс

  • HAL-ы

Архитектура микродроида

Microdroid похож на Cuttlefish тем, что обе системы имеют архитектуру, схожую со стандартным Android. Microdroid состоит из следующих образов разделов, сгруппированных в составной образ диска:

  • bootloader — проверяет и запускает ядро.
  • boot.img - Содержит ядро ​​и init ramdisk.
  • vendor_boot.img — содержит специфичные для виртуальной машины модули ядра, такие как virtio.
  • super.img - Состоит из системных и вендорных логических разделов.
  • vbmeta.img — содержит проверенные метаданные загрузки.

Образы разделов поставляются в составе Virtualization APEX и упаковываются в составной образ диска службой VirtualizationService . Помимо основного составного образа диска ОС, VirtualizationService отвечает за создание следующих разделов:

  • payload — набор разделов, поддерживаемых APEX и APK Android
  • instance — зашифрованный раздел для сохранения проверенных загрузочных данных для каждого экземпляра, таких как соль для каждого экземпляра, доверенные открытые ключи APEX и счетчики откатов.

Последовательность загрузки

Последовательность загрузки Microdroid выполняется после загрузки устройства . Загрузка устройства обсуждается в разделе «Прошивка pVM» документа «Архитектура» . На рисунке 1 показаны этапы загрузки Microdroid:

Безопасная загрузка экземпляра microdroid

Рисунок 1. Безопасная загрузка экземпляра MicroDroid

Вот объяснение шагов:

  1. Загрузчик загружается в память с помощью crosvm, и pvmfw начинает выполняться. Перед переходом к загрузчику pvmfw выполняет две задачи:

    • Проверяет загрузчик на предмет получения его из надежного источника (Google или OEM).
    • Обеспечивает единообразное использование одного и того же загрузчика при нескольких загрузках одной и той же pVM благодаря использованию образа экземпляра. В частности, pVM изначально загружается с пустым образом экземпляра. pvmfw сохраняет идентификатор загрузчика в образе экземпляра и шифрует его. Таким образом, при следующей загрузке pVM с тем же образом экземпляра pvmfw расшифровывает сохранённый идентификатор из образа экземпляра и проверяет, что он совпадает с ранее сохранённым. Если идентификаторы различаются, pvmfw отказывается от загрузки.

    Затем загрузчик загружает Microdroid.

  2. Загрузчик обращается к диску экземпляра. Подобно pvmfw, загрузчик имеет диск экземпляра, содержащий информацию об образах разделов, использованных в этом экземпляре во время предыдущих загрузок, включая открытый ключ.

  3. Загрузчик проверяет vbmeta и связанные разделы, такие как boot и super , и в случае успеха извлекает секреты pVM следующего этапа. Затем Microdroid передаёт управление ядру.

  4. Поскольку суперраздел уже проверен загрузчиком (шаг 3), ядро ​​безоговорочно монтирует его. Как и в полной версии Android, суперраздел состоит из нескольких логических разделов, смонтированных через dm-verity. Затем управление передаётся процессу init , который запускает различные нативные службы. Скрипт init.rc аналогичен скрипту полной версии Android, но адаптирован под нужды Microdroid.

  5. Процесс init запускает диспетчер Microdroid, который обращается к образу экземпляра. Служба диспетчера Microdroid расшифровывает образ, используя ключ, переданный на предыдущем этапе, и считывает открытые ключи и счетчики откатов клиентских APK и APEX, которым доверяет данная pVM. Эта информация впоследствии используется zipfuse и apexd при монтировании клиентского APK и запрошенных APEX соответственно.

  6. Служба менеджера Microdroid запускает apexd .

  7. apexd монтирует APEX-файлы в каталоги /apex/<name> . Единственное различие между монтированием APEX-файлов в Android и Microdroid заключается в том, что в Microdroid файлы APEX берутся из виртуальных блочных устройств ( /dev/vdc1 и т.д.), а не из обычных файлов ( /system/apex/*.apex ).

  8. zipfuse — это файловая система FUSE от Microdroid. zipfuse монтирует клиентский APK, который по сути представляет собой ZIP-файл, как файловую систему. В дальнейшем APK-файл передаётся pVM как виртуальное блочное устройство с dm-verity, как и APEX. APK содержит файл конфигурации со списком APEX-файлов, запрошенных разработчиком приложения для данного экземпляра pVM. Этот список используется apexd при активации APEX-файлов.

  9. Процесс загрузки возвращается к службе-менеджеру Microdroid. Затем служба-менеджер взаимодействует со VirtualizationService Android с помощью Binder RPC, чтобы сообщать о важных событиях, таких как сбой или завершение работы, и принимать запросы, например, на завершение работы pVM. Служба-менеджер считывает местоположение основного исполняемого файла из конфигурационного файла APK и выполняет его.

Обмен файлами (AuthFS)

Компоненты Android часто используют файлы для ввода, вывода и состояния, передавая их как файловые дескрипторы (тип ParcelFileDescriptor в AIDL) с доступом, контролируемым ядром Android. AuthFS обеспечивает аналогичную функциональность для обмена файлами между конечными точками, не доверяющими друг другу, через границы pVM.

По сути, AuthFS — это удалённая файловая система с прозрачными проверками целостности отдельных операций доступа, аналогичными fs-verity . Эти проверки позволяют фронтенду, например, программе чтения файлов, работающей в виртуальной машине с физическими данными (pVM), обнаруживать, что недоверенный бэкенд, обычно Android, внёс изменения в содержимое файла.

Для обмена файлами бэкенд ( fd\_server ) запускается с настройкой для каждого файла, указывающей, предназначен ли он для ввода (только чтение) или вывода (чтение и запись). Для ввода фронтенд проверяет соответствие содержимого известному хешу на основе дерева Меркла для проверки при доступе. Для вывода AuthFS поддерживает внутреннее хеш-дерево содержимого, полученное при операциях записи, и может обеспечивать целостность при обратном чтении данных.

В настоящее время базовый транспорт основан на Binder RPC, однако в будущем это может измениться для оптимизации производительности.

Управление ключами

pVM снабжены стабильным ключом запечатывания , который подходит для защиты постоянных данных, и ключом подтверждения , который подходит для создания подписей, проверяемых pVM.

Связующее RPC

Большинство интерфейсов Android реализованы в AIDL , который построен на основе драйвера ядра Linux Binder. Для поддержки интерфейсов между pVM протокол Binder был переписан для работы через сокеты, в случае pVM — через vsock . Работа через сокеты позволяет использовать существующие интерфейсы AIDL Android в этой новой среде.

Для настройки соединения одна конечная точка, например, полезная нагрузка pVM, создаёт объект RpcServer , регистрирует корневой объект и начинает прослушивать новые соединения. Клиенты могут подключиться к этому серверу с помощью объекта RpcSession , получить объект Binder и использовать его точно так же, как объект Binder используется с драйвером Binder ядра.