2025 年 3 月 27 日より、AOSP のビルドとコントリビューションには aosp-main
ではなく android-latest-release
を使用することをおすすめします。詳細については、AOSP の変更をご覧ください。
Microdroid
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
Microdroid は pVM で動作する小型の Android OS です。Microdroid を使用する必要はなく、VM は任意の OS で起動できます。しかし、pVM の主なユースケースはスタンドアロン OS を実行することではなく、Android が提供するよりも優れた機密性と整合性が確保された、アプリの一部を実行するための分離された実行環境を提供することです。
従来のオペレーティング システムでは、優れた機密性と整合性を確保するためにかなりの作業が必要になります(多くの場合、重複します)。なぜなら、従来型オペレーティング システムは包括的な Android アーキテクチャに適していないためです。たとえば、標準の Android アーキテクチャでは、デベロッパーはアプリの一部を pVM で安全に読み込んで実行する手段を実装する必要があり、ペイロードは glibc に対してビルドされます。Android アプリは Bionic を使用し、通信には vsock にカスタム プロトコルが必要で、adb を使用してデバッグするのは困難です。
Microdroid は、こうしたギャップを埋めるために、デベロッパーがアプリの一部を pVM にオフロードするための最小労力で設計された既製の OS イメージを提供しています。ネイティブ コードは Bionic に対してビルドされ、Binder で通信が行われます。また、ホストの Android から APEX をインポートし、ハードウェア格納型鍵を使用する暗号オペレーションのキーストアなど、Android API のサブセットを公開できます。全体的に、デベロッパーにとって Microdroid は完全な Android OS と似通った環境のツールであると言えます。
機能
Microdroid は Android の軽量化バージョンであり、pVM に固有の追加コンポーネントを備えています。Microdroid は以下をサポートしています。
- NDK API のサブセット(Android で libc と Bionic を実装するためのすべての API が提供されています)
- adb、logcat、tombstone、gdb などのデバッグ機能
- 確認付きブートと SELinux
- APK に埋め込まれた共有ライブラリとバイナリの読み込みと実行
- vsock の Binder RPC と暗黙的な整合性チェックによるファイルのエクスチェンジ
- APEX の読み込み
Microdroid は以下をサポートしていません。
Microdroid アーキテクチャ
Microdroid は Cuttlefish と類似しており、どちらも標準の Android に似たアーキテクチャを備えています。Microdroid は、以下のパーティション イメージから構成され、複合ディスク イメージにグループ化されています。
bootloader
- カーネルを検証して起動します。
boot.img
- カーネルと init RAM ディスクが含まれます。
vendor_boot.img
- virtio などの VM 固有のカーネル モジュールが含まれます。
super.img
- システムとベンダーの論理パーティションで構成されます。
vbmeta.img
- 確認付きブートのメタデータが含まれます。
パーティション イメージは Virtualization APEX で提供され、VirtualizationService
によって複合ディスク イメージにパッケージ化されます。VirtualizationService
は、メインの OS 複合ディスク イメージだけでなく、次のパーティションも作成します。
payload
- Android の APEX と APK に基づくパーティションのセット
instance
- インスタンスごとのソルト、信頼できる APEX 公開鍵、ロールバック カウンタなど、インスタンスごとの確認付きブートデータを保持するための暗号化されたパーティション
起動シーケンス
Microdroid の起動シーケンスは、デバイスの起動の後に行われます。デバイスの起動については、アーキテクチャのドキュメントの pVM ファームウェア セクションをご覧ください。図 1 は、Microdroid の起動シーケンスで発生する手順を示しています。
図 1. microdroid インスタンスの安全なブートフロー
以下に手順を説明します。
ブートローダーが crosvm によってメモリに読み込まれ、pvmfw が実行を開始します。pvmfw は、ブートローダーにアクセスする前に次の 2 つのタスクを実行します。
- ブートローダーが信頼できるソース(Google または OEM)からのものかどうかを確認します。
- インスタンス イメージを使用して、同じ pVM の複数回のブートにわたって同じブートローダーを一貫して使用するようにします。具体的には、pVM は最初に空のインスタンス イメージで起動します。pvmfw は、ブートローダーの ID をインスタンス イメージに格納し、暗号化します。このため、次回同じインスタンス イメージを使用して pVM を起動すると、pvmfw はインスタンス イメージから保存された ID を復号し、以前に保存された ID と同じであることを確認します。ID が異なる場合、pvmfw は起動を拒否します。
ブートローダーによって Microdroid が起動します。
ブートローダーはインスタンス ディスクにアクセスします。pvmfw と同様に、ブートローダーにはインスタンス ディスク ドライブがあり、前回のブート時にこのインスタンスで使用されていたパーティション イメージに関する情報(公開鍵を含む)が格納されています。
ブートローダーが vbmeta とチェーンされたパーティション(boot
や super
など)を検証し、成功すると、次のステージの pVM のシークレットを取得します。その後、Microdroid はカーネルに制御を引き継ぎます。
スーパー パーティションはブートローダーによってすでに検証されているため(ステップ 3)、カーネルはスーパー パーティションを無条件にマウントします。完全な Android と同様に、スーパー パーティションは dm-verity でマウントされた複数の論理パーティションで構成されています。次に、コントロールが init
プロセスに渡され、さまざまなネイティブ サービスが開始されます。init.rc
スクリプトは、完全な Android のスクリプトに似ていますが、Microdroid のニーズに合わせて調整されています。
init
プロセスは、インスタンス イメージにアクセスする Microdroid マネージャーを起動します。Microdroid マネージャー サービスは、前のステージから渡された鍵を使用してイメージを復号し、この pVM が信頼するクライアント APK と APEX の公開鍵とロールバック カウンタを読み取ります。この情報は、後で zipfuse
と apexd
がクライアント APK をマウントし、APEX をリクエストしたときに使用されます。
Microdroid マネージャー サービスは apexd
から開始します。
apexd
は、APEX を /apex/<name>
ディレクトリにマウントします。Android と Microdroid による APEX のマウントの唯一の違いは、Microdroid では APEX ファイルが通常のファイル(/system/apex/*.apex
)ではなく、仮想ブロック デバイス(/dev/vdc1
, …)から取得される点です。
zipfuse
は Microdroid の FUSE ファイル システムです。zipfuse
は、基本的には ZIP ファイルをファイル システムとするクライアント APK をマウントします。この APK ファイルは、APEX と同様、dm-verity を使用した pVM によって仮想ブロック デバイスとして渡されます。この APK には、アプリ デベロッパーがこの pVM インスタンスについてリクエストした APEX のリストを含む構成ファイルが含まれています。このリストは、APEX を有効にするときに apexd
によって使用されます。
起動フローは Microdroid マネージャー サービスに戻ります。マネージャー サービスは、Binder RPC を使用して Android の VirtualizationService
と通信し、クラッシュやシャットダウンなどの重要なイベントをレポートしたり、pVM の終了などのリクエストを承認したりできるようにします。マネージャー サービスが APK の構成ファイルからメインバイナリの場所を読み取って実行します。
ファイル交換(AuthFS)
Android コンポーネントでは、入力、出力、状態のファイルを使用し、これらをファイル記述子(AIDL では ParcelFileDescriptor
型)として渡し、Android カーネルでアクセスを制御するのが一般的です。AuthFS を使用すると、pVM の境界を越えて相互に信頼していないエンドポイント間でファイルを交換する際に、同様の機能を実現できます。
基本的に、AuthFS はリモート ファイル システムで fs-verity
と同様に、個々のアクセス オペレーションの透明性の高い整合性チェックを行います。このチェックにより、pVM で実行されるファイル読み取りプログラムなどのフロントエンドは、信頼できないバックエンド(通常は Android)がファイルの内容を改ざんしたかどうかを検出できます。
ファイルを交換するために、バックエンド(fd\_server
)は入力用(読み取り専用)か出力用(読み取りと書き込み)かを指定するファイルごとの構成で開始されます。入力の場合、アクセス時の検証用のマークルツリーに加え、フロントエンドはコンテンツを既知のハッシュと一致させます。出力の場合、AuthFS は書き込みオペレーションから観測されたコンテンツのハッシュツリーを内部的に維持し、データが読み取られるときに整合性を適用します。
基盤となるトランスポートは現在 Binder RPC に基づいていますが、将来的にはパフォーマンスを最適化するために変更される可能性があります。
鍵の管理
pVM は、保護対象の永続データに適している安定したシーリングキーや、pVM によって検証可能な方法で生成された署名を生成するのに適している証明書鍵によって提供されます。
Binder リモート プロシージャ コール
Android のインターフェースの大部分は AIDL で表現されており、Binder Linux カーネル ドライバ上に構築されています。pVM 間のインターフェースをサポートするため、Binder プロトコルは、ソケット(vsock、pVM の場合)で動作するように書き換えられました。ソケットを介して操作すると、Android の既存の AIDL インターフェースをこの新しい環境で使用できます。
接続を設定するために、pVM ペイロードなどの 1 つのエンドポイントが RpcServer
オブジェクトを作成し、ルート オブジェクトを登録して、新しい接続をリッスンします。クライアントは、RpcSession
オブジェクトを使用してこのサーバーに接続し、Binder
オブジェクトを取得します。カーネル Binder ドライバで Binder
オブジェクトを使用する場合と同じように使用できます。
このページのコンテンツやコードサンプルは、コンテンツ ライセンスに記載のライセンスに従います。Java および OpenJDK は Oracle および関連会社の商標または登録商標です。
最終更新日 2025-03-02 UTC。
[[["わかりやすい","easyToUnderstand","thumb-up"],["問題の解決に役立った","solvedMyProblem","thumb-up"],["その他","otherUp","thumb-up"]],[["必要な情報がない","missingTheInformationINeed","thumb-down"],["複雑すぎる / 手順が多すぎる","tooComplicatedTooManySteps","thumb-down"],["最新ではない","outOfDate","thumb-down"],["翻訳に関する問題","translationIssue","thumb-down"],["サンプル / コードに問題がある","samplesCodeIssue","thumb-down"],["その他","otherDown","thumb-down"]],["最終更新日 2025-03-02 UTC。"],[],[],null,["# Microdroid is a mini-Android OS that runs in a pVM. You don't have to use\nMicrodroid, you can start a VM with any OS. However, the primary use cases\nfor pVMs aren't running a standalone OS but rather offering an isolated\nexecution environment for running a portion of an app with stronger\nconfidentiality and integrity guarantees than Android can provide.\n\nWith traditional operating systems, providing strong confidentiality and\nintegrity requires a fair amount of work (often duplicated)\nbecause traditional operating systems don't fit with the overarching Android\narchitecture. For example, with the standard Android architecture, developers\nneed to implement a means of securely loading and executing part of their app\nin the pVM, and the payload is built against glibc. The Android app uses\nBionic, communication requires a custom protocol over vsock, and debugging using\nadb is challenging.\n\nMicrodroid fills these gaps by providing an off-the-shelf OS image designed to\nrequire the least amount of effort from developers to offload a portion of\ntheir app into a pVM. Native code is built against Bionic, communication happens\nover Binder, and it allows importing APEXes from the host Android and exposes\na subset of the Android API, such as keystore for cryptographic operations with\nhardware-backed keys. Overall, developers should find Microdroid a familiar\nenvironment with the tools they've grown accustomed in the full Android OS.\n\nFeatures\n--------\n\nMicrodroid is a stripped down version of Android with a few additional\ncomponents specific to pVMs. Microdroid supports:\n\n- A subset of NDK APIs (all APIs for Android's implementation of libc and Bionic are provided)\n- Debugging features, such as adb, logcat, tombstone, and gdb\n- Verified Boot and SELinux\n- Loading and executing a binary, together with shared libraries, embedded in an APK\n- Binder RPC over vsock and exchange of files with implicit integrity checks\n- Loading of APEXes\n\nMicrodroid doesn't support:\n\n- Android Java APIs in the `android.\\*` packages\n\n | **Note:** Core Java APIs in the `java.\\*` packages can be supported by activating the ART APEX in the VM.\n- SystemServer and Zygote\n\n- Graphics/UI\n\n- HALs\n\nMicrodroid architecture\n-----------------------\n\nMicrodroid is similar to\n[Cuttlefish](/docs/devices/cuttlefish) in that both have an architecture that's\nsimilar to standard Android. Microdroid consists of the following partition\nimages grouped together in a composite disk image:\n\n- `bootloader` - Verifies and starts the kernel.\n- `boot.img` - Contains the kernel and init ramdisk.\n- `vendor_boot.img` - Contains VM-specific kernel modules, such as virtio.\n- `super.img` - Consists of system and vendor logical partitions.\n- `vbmeta.img` - Contains verified boot metadata.\n\nThe partition images ship in the Virtualization APEX and are packaged in\na composite disk image by `VirtualizationService`. In addition to the main\nOS composite disk image, `VirtualizationService` is responsible for creating\nthese other partitions:\n\n- `payload` - A set of partitions backed by Android's APEXes and APKs\n- `instance` - An encrypted partition for persisting per-instance verified boot data, such as per-instance salt, trusted APEX public keys, and rollback counters\n\nBoot sequence\n-------------\n\nThe Microdroid boot sequence occurs after\n[Device boot](/docs/core/virtualization/architecture#device-boot). Device boot is\ndiscussed in the pVM Firmware section of the [Architecture](/docs/core/virtualization/architecture)\ndocument. Figure 1 shows the steps that take place during the Microdroid boot\nsequence:\n\n\n**Figure 1.** Secure bootflow of microdroid instance\n\n\u003cbr /\u003e\n\nHere's an explanation of the steps:\n\n1. The bootloader is loaded into memory by crosvm and pvmfw starts\n executing. Before jumping to the bootloader, pvmfw performs two tasks:\n\n - Verifies the bootloader to check if it is from a trusted source (Google or an OEM).\n - Ensures that the same bootloader is used consistently across multiple boots of the same pVM through the use of the instance image. Specifically, the pVM is initially booted with an empty instance image. pvmfw stores the identity of the bootloader in the instance image and encrypts it. So, the next time the pVM is booted with the same instance image, pvmfw decrypts the saved identity from the instance image and verifies that it's the same that was previously saved. If the identities differ, pvmfw refuses to boot.\n\n The bootloader then boots Microdroid.\n2. The bootloader accesses the instance disk. Similar to pvmfw, the\n bootloader has an instance disk drive with information about partition images\n used in this instance during previous boots, including the public key.\n\n3. The bootloader verifies vbmeta and the chained partitions, such as `boot`\n and `super`, and, if successful, derives the next-stage pVM secrets.\n Then, Microdroid hands control over to the kernel.\n\n4. Because the super partition has already been verified by the bootloader\n (step 3), the kernel unconditionally mounts the super partition. As with the\n full Android, the super partition consists of multiple logical partitions\n mounted over dm-verity. Control is then passed to the `init` process, which\n starts various native services. The `init.rc` script is similar to that of full\n Android but tailored to the needs of Microdroid.\n\n5. The `init` process starts the Microdroid manager, which accesses the instance\n image. The Microdroid manager service decrypts the image using the key passed\n from the previous stage and reads the public keys and rollback counters of the\n client APK and APEXes that this pVM trusts. This information is used later by\n `zipfuse` and `apexd` when they mount the client APK and requested APEXes,\n respectively.\n\n6. The Microdroid manager service starts `apexd`.\n\n7. `apexd` mounts the APEXes at `/apex/\u003cname\u003e` directories. The only difference\n between how Android and Microdroid mount APEXes is that in\n Microdroid, the APEX files are coming from virtual block devices\n (`/dev/vdc1`, ...), not from regular files (`/system/apex/*.apex`).\n\n8. `zipfuse` is Microdroid's FUSE file system. `zipfuse` mounts the client APK,\n which is essentially a Zip file as a file system. Underneath, the APK file is\n passed as a virtual block device by the pVM with dm-verity, same as APEX. The\n APK contains a config file with a list of APEXes that the app developer has\n requested for this pVM instance. The list is used by `apexd` when activating\n APEXes.\n\n9. The boot flow returns to the Microdroid manager service. The manager\n service then communicates with Android's `VirtualizationService` using\n Binder RPC so that it can report important events like crash or shutdown,\n and accept requests such as terminating the pVM. The manager service reads the\n location of the main binary from the APK's config file and executes it.\n\nFile exchange (AuthFS)\n----------------------\n\nIt's common for Android components to use files for input, output, and state\nand to pass these around as file descriptors (`ParcelFileDescriptor` type in\nAIDL) with access controlled by the Android kernel. AuthFS facilitates similar\nfunctionality for exchanging files between mutually distrusting endpoints\nacross pVM boundaries.\n\nFundamentally, AuthFS is a remote file system with transparent integrity checks\non individual access operations, similar to `fs-verity`. The checks allow the\nfrontend, such as a file-reading program running in a pVM, to detect if the\nuntrusted backend, typically Android, tampered with file content.\n\nTo exchange files, the backend (`fd\\_server`) is started with per-file\nconfiguration specifying whether it's meant for input (read-only) or output\n(read-write). For input, the frontend enforces that the contents match a known\nhash, on top of a Merkle tree for on-access verification. For output, AuthFS\ninternally maintains a hash tree of the contents as observed from write\noperations and can enforce integrity when the data are read back.\n\nThe underlying transport is currently based on Binder RPC, however that might\nchange in the future to optimize performance.\n\nKey management\n--------------\n\npVMs are provided with a stable *sealing key* that's suitable for protecting\npersistent data, and an *attestation key* that's suitable for producing\nsignatures that are verifiably produced by the pVM.\n\nBinder RPC\n----------\n\nA majority of Android's interfaces are expressed in\n[AIDL](https://developer.android.com/guide/components/aidl), which\nis built on top of the Binder Linux kernel driver. To support interfaces\nbetween pVMs, the Binder protocol has been rewritten to work over sockets,\n[vsock](/docs/core/virtualization/virtualization-service#vm-sockets)\nin the case of pVMs. Operating over sockets allows Android's existing AIDL\ninterfaces to be used in this new environment.\n\nTo set up the connection, one endpoint, such as pVM payload, creates\nan `RpcServer` object, registers a root object, and begins listening for new\nconnections. Clients can connect to this server using an `RpcSession` object,\nget the `Binder` object, and use it exactly like a `Binder` object is used\nwith the kernel Binder driver."]]