Safeguard
Supply Chain Security•

Android Virtualization Framework and pKVM Explained: Protected VMs

Android's AVF uses the pKVM hypervisor at EL2 to run protected VMs whose memory the Android host cannot read. How pKVM, Microdroid and attestation work.

Safeguard Security Team
37 min read

The Android Virtualization Framework (AVF) lets Android run small virtual machines, called protected VMs (pVMs), whose memory the main Android system cannot read or change, even if the Android kernel is compromised. It arrived with Android 13, runs on ARM64, and is enforced by pKVM, a hypervisor at exception level 2 built from Linux KVM.

This post walks through pKVM's memory model, what a protected VM can and cannot hide, how Microdroid boots and proves what it runs, which workloads use AVF today, and how to try it on a supported device. Everything comes from the Android Open Source Project (AOSP) documentation, the AVF source tree and the Linux kernel documentation, listed under Sources.

Key takeaways

  • AVF is Android's VM layer for isolation. Android 13 introduced it as "secure virtualization" for security use cases that need stronger isolation than the app sandbox. Protected VMs need ARM64.
  • pKVM makes the guarantee. It runs at EL2, the Android kernel drops to EL1 during boot, and pKVM keeps stage 2 page tables on even for the host, so the host loses access to pages it donates to a guest.
  • The host is untrusted for confidentiality and integrity, but controls availability. A compromised host cannot read a pVM's memory, yet it can refuse to schedule it.
  • Microdroid is a cut down Android for pVMs. It boots through pVM firmware (pvmfw), Android Verified Boot and dm-verity, mounts a signed APK and APEXes, and runs one native payload that talks to Android over Binder on vsock.
  • Identity comes from a DICE chain. VM remote attestation, strongly recommended from Android 15, gives a pVM a certificate chain backed by Remote Key Provisioning that lists every APK and APEX it loaded.
  • AVF does not replace TrustZone, not every device supports protected VMs, and the guest OS and payload are their own dependency set to track and patch.

What is the Android Virtualization Framework, and why did Google build it?

AOSP defines AVF as providing "secure and private execution environments for executing code," aimed at security use cases that need stronger isolation assurances than Android's app sandbox, some of which AOSP says can even be formally verified. Android ships a reference implementation of every component.

The AOSP "Why AVF?" page explains the reasoning. Operating systems isolate processes with the memory management unit, and only the trusted computing base (TCB) may program it. On Android that TCB is the Linux kernel, which AOSP describes as over 20 million lines of code, including drivers, schedulers, file systems, the network stack and executable loaders. The bigger the TCB, the harder it is to rule out an exploitable bug, and one kernel bug can expose every app's secrets.

The existing answer is Arm TrustZone: the processor runs in a Secure or Non-secure state, memory is tagged accordingly, and a secure world serves the normal world on demand. AOSP lists three limits of that model:

  1. Only two domains. Every new use case that needs isolation from Android adds code to the same secure world, growing its attack surface, and a bug there can compromise the whole device.
  2. Static allocation. TrustZone deployments assume resources are allocated ahead of time and handle on demand use cases poorly.
  3. Fragmented APIs. Interfaces outside Android differ across vendors, which AOSP says limits deployment at Android scale, even for fundamentals like KeyMint and Gatekeeper.

AVF answers with VMs created on demand, isolated from Android and from each other, behind one standard API on every supporting device. AOSP is explicit that this is an addition, not a swap: AVF does not fully replace TrustZone, because Android SoCs cannot function without it.

For the TrustZone side of the picture, see our posts on how trusted execution environments protect sensitive workloads and on Arm Trusted Firmware A and the secure world. For where AVF sits among Android's other security features, see our Android release history of security features.

The parts of AVF

ComponentRole, per AOSP
pKVMHypervisor built on Linux KVM at EL2; keeps pVM code and data confidential and intact even if Android or another pVM is compromised
crosvmVirtual machine monitor (VMM) written in Rust; allocates VM memory, creates vCPU threads, implements virtual devices
VirtualizationServiceAndroid service that manages VM lifecycles by managing crosvm instances
pvmfwpVM firmware, the first code in a pVM; verifies the payload and derives the per VM secret
Microdroid and Microdroid ManagerA Google provided mini Android for pVMs, and its in-VM lifecycle manager
apexd, zipfuse, authfsMount host APEXes and APKs securely, and share files with integrity checks
Binder over vsockThe main inter VM communication path

Timeline by Android version

WhenWhat changedSource
Android 12Remote Key Provisioning (RKP) becomes part of AOSPAOSP RKP page
Android 13AVF introduced; pvmfw partition build support starts ("Android T"); pKVM in GKI configs for android13 5.x kernelsWhy AVF?, pvmfw README, Try AVF
KVM Forum 2022Protected KVM on arm64 deep dive talk, still cited by kernel docsKernel pKVM doc
Android 14RKP becomes an updatable Mainline module; Google's first AVF capable reference phones need Android 14 before pKVM can be enabledAOSP RKP page, AVF getting started
Android 15 ("V")VM remote attestation becomes strongly recommended; Linux development environment appears in Android 15 release notesVM remote attestation doc, AVF use cases
Current upstream docsUpstream Linux calls pKVM experimental and lists DMA isolation and pvmfw as unimplemented upstreamKernel pKVM doc

The last row matters. Android's pKVM lives in the Android Common Kernel and GKI, which carry work upstream Linux has not merged. When you read a pKVM claim, check which kernel it describes.

How does pKVM work?

Exception levels

Arm defines up to four exception levels. On Android, userspace runs at EL0, the Linux kernel at EL1, secure monitor firmware at EL3, and pKVM at EL2.

KVM on arm64 has modes. On CPUs with the Virtualization Host Extensions (ARMv8.1 and later) the host kernel can run at EL2. In non VHE (nVHE) mode, the hypervisor code is split out of the kernel at boot and installed at EL2 while the kernel runs at EL1. That EL2 piece is small; it switches between EL1 contexts. pKVM extends it so it can restrict the host kernel and userspace, including their access to guest memory and the hypervisor. The upstream kernel's kvm-arm.mode parameter accepts none, nvhe, protected and nested, and booting with kvm-arm.mode=protected enables pKVM.

The boot sequence that deprivileges Android

AOSP describes three phases:

  1. Initialization. The bootloader enters the generic kernel at EL2. Trusted code at EL2 and EL1 sets up pKVM and its modules. No untrusted code runs yet.
  2. Deprivilege. The kernel sees it is at EL2 and drops itself to EL1. pKVM and its modules stay at EL2.
  3. Runtime. The kernel boots normally to userspace, with pKVM owning the stage 2 page tables.

The bootloader is trusted to verify the kernel before initialization (where Android Verified Boot does its job). After the drop, the hypervisor no longer trusts the kernel and must protect itself even if the kernel is compromised.

The hypervisor and kernel ship in one binary, so they always update atomically and their interface need not stay stable. With GKI, pKVM reaches devices inside the kernel image: a kernel update is a hypervisor update. AOSP also documents pKVM vendor modules, which let SoC vendors port device specific EL2 functions such as IOMMU drivers; they load during the trusted phase and become part of the hypervisor's TCB.

Stage 2 page tables

Arm MMUs translate in two stages. Stage 1, controlled at EL1, gives each process its virtual address space. Stage 2, controlled at EL2, translates the stage 1 output (an intermediate physical address, IPA) into a physical address.

Historically KVM enabled stage 2 only while a guest ran, so the host could read any guest page. pKVM keeps stage 2 on in host context too, which puts the hypervisor, not the host kernel, in charge of which pages the host may map. For the host, stage 2 is identity mapped and used only for access control. That keeps large mappings possible (less TLB pressure) and lets the hypervisor track page ownership directly in the host's page table, using entry bits reserved for software.

Memory donation, sharing and relinquishing

At boot, all non hypervisor memory belongs to the host. When a pVM is created, the host donates pages; the hypervisor moves ownership to the pVM and removes them from the host's stage 2 mappings.

OperationWho starts itEffect
DonateHost, when creating or growing a pVMOwnership moves to the pVM; host loses access
Share and unshareGuest, by hypercallGuest picks pages the host may access, such as virtio buffers, and can revoke them
RelinquishGuest, by hypercallGuest returns pages to the host without shutting down; used with the virtio balloon

The upstream kernel names the hypercalls, including ARM_SMCCC_KVM_FUNC_HYP_MEMINFO (which reports the protection granule), ARM_SMCCC_KVM_FUNC_MEM_SHARE, ARM_SMCCC_KVM_FUNC_MEM_UNSHARE and ARM_SMCCC_KVM_FUNC_MMIO_GUARD. A Linux guest needs CONFIG_ARM_PKVM_GUEST=y to issue them.

If the host touches a page it no longer owns, AOSP says the hypervisor injects a synchronous exception: the task gets SIGSEGV or the host kernel crashes. Donated pages cannot be swapped or merged. The kernel page adds details VMM authors will meet: memslots cannot move once a pVM runs, dirty logging is unsupported, donated pages count against RLIMIT_MLOCK, and a system call touching unshared pVM memory fails with EFAULT or forcibly reclaims the page, which the hypervisor zeroes first. When a pVM stops, its memory is wiped before returning to the host, and AOSP says all pVM and pvmfw memory from one boot is wiped before the bootloader runs on the next.

DMA protection

Unmapping pages from the CPU is not enough: DMA capable devices are controlled by the host kernel. AOSP states pKVM requires an IOMMU for every DMA capable device, and recommends the Arm System MMU (SMMU) as the reference. To keep SoC specific code out of EL2, the host handles auxiliary IOMMU tasks such as power management, while the hypervisor keeps the permission checks. The IOMMU must ensure those checks cannot be bypassed, for example after a device reset. This is one reason AOSP says SoC vendors must meet new requirements to support pKVM, without which confidentiality cannot be provided.

Interrupts, MMIO and the MMIO guard

KVM delegates virtual interrupt management to the host, which acts as an untrusted part of the hypervisor. pKVM keeps that model with full GICv3 emulation; timers and inter processor interrupts are handled there too.

MMIO is where data could leak. When a guest touches an address with no memory behind it, the vCPU exits to the host to emulate a device, and pKVM must report the faulting instruction, possibly with register contents. pKVM's MMIO guard makes such faults fatal unless the guest first registered that IPA range by hypercall. The guest opts in region by region.

virtio and bounce buffers

Most pVM devices are virtio, which also carries vsock. Virtio assumes the host can read guest memory, which pKVM breaks on purpose, and page granular sharing could expose unrelated data next to a small buffer. So the guest allocates virtqueues and data buffers from a fixed shared window and copies data in and out: bounce buffers.

Talking to TrustZone without a back door

The host still needs secure monitor calls (SMCs), and an SMC can name a physical buffer the secure world cannot check ownership of. A malicious host could ask the secure world to touch a pVM's pages, which AOSP calls a confused deputy attack. pKVM traps every host SMC at EL2 and proxies it. PSCI power calls pass through with the CPU entry point rewritten so stage 2 is installed before the host resumes. Firmware Framework for Arm (FF-A) messages are checked so the host cannot share memory it does not own. Everything else goes to EL3 firmware. AOSP recommends an up to date Trusted Firmware A at EL3 and, on systems with S-EL2, a Secure Partition Manager Core such as Hafnium.

crosvm and scheduling

Each crosvm process runs one VM using standard KVM ioctls (KVM_CREATE_VM, KVM_SET_USER_MEMORY_REGION, KVM_RUN). pKVM adds KVM_CAP_ARM_PROTECTED_VM, which crosvm uses for a protected VM to reserve pvmfw memory and enable protected mode; upstream documents the machine type KVM_VM_TYPE_ARM_PROTECTED. Each vCPU is a POSIX thread scheduled by Linux, which is why the host controls availability. Only the EL2 code itself is non preemptible.

Protected VM versus non protected VM: what can the host not see?

A non protected VM is an ordinary KVM guest: crosvm can access all its memory. A protected VM is created in protected mode, so donated memory leaves the host's view.

PropertyNon protected VMProtected VM
Host can read guest memoryYesNo, except pages the guest shares
First code to runWhatever crosvm loadspvmfw, loaded by the hypervisor from protected memory
Boot image verificationOptionalRequired; failure resets the VM
Per instance DICE secretsNot providedDerived by pvmfw, only for that instance
MMIO trapsAnywhereFatal unless registered with the MMIO guard
Cuttlefish and x86_64Supported (x86_64 for testing)Not supported
Example useLinux development environmentIsolated compilation, content safety

What a compromised host cannot do

AOSP's security page lists properties that hold even after host compromise. A pVM's pages cannot be accessed by another entity unless the owner shares them, for CPU and DMA alike. Pages are wiped before returning to the host. With a hardware debugger such as SJTAG attached, a pVM cannot reach keys it minted earlier. pvmfw refuses to boot an unverifiable image or a tampered instance image. Only that instance can derive its DICE chain and CDIs. pVMs cannot change each other's memory or CPU state without consent.

AOSP puts the size difference plainly: the EL2 part of pKVM is roughly 10 thousand lines, against roughly 20 million for the kernel, three orders of magnitude less attack surface. That size makes formal verification realistic, and AOSP says Google supports research to prove these properties on the actual pKVM binary.

What the host still controls

pKVM keeps confidentiality and integrity, not availability. The host schedules vCPUs and can never run one, handles physical interrupts (AOSP aims to make mishandling only a denial of service), and through the VMM can withhold memory and devices. In reverse, the host can always stop a guest and reclaim its resources.

Some properties are maintained by Android as host and do not survive host compromise: only VirtualizationService can open a channel to a pVM, only apps signed with the platform key can request permission to create or interact with pVMs, guest pVMs cannot open vsock connections to each other, and context identifiers (CIDs) are not reused while the host runs.

Two more limits. AOSP says pKVM protects against attacks on the host OS, while "actors who have access to the device's supply chain, such as OEMs and SoC vendors, are still necessarily trusted." And an unlocked bootloader breaks the model: unlocking wipes user data and invalidates pVM private data, after which pvmfw and pKVM can be reflashed. Remote parties can see that state in the verified boot fields of a key attestation certificate.

What is Microdroid, and how is it booted and verified?

Microdroid is a mini Android OS for pVMs. A pVM can run any OS crosvm supports if it is properly signed, but AOSP explains why Microdroid exists: the main use for pVMs is running part of an app with stronger guarantees, and a generic Linux guest would force developers to build a secure loader, compile against glibc instead of Bionic, invent a vsock protocol and give up adb.

Microdroid supportsMicrodroid leaves out
A subset of NDK APIs, including all of Bionic libcAndroid Java APIs in the android packages
adb, logcat, tombstones and gdbSystemServer and Zygote
Verified Boot and SELinuxGraphics and UI
A binary and shared libraries embedded in an APKHALs
Binder RPC over vsock, file exchange with integrity checks, APEX loading (ART APEX for core java packages), keystore

AOSP layers enforcement: only apps with pVM permission can create or inspect pVMs, the bootloader boots only pVM images signed by Google or the device vendor (so apps cannot bundle their own kernels), and SELinux in the pVM forbids executable data mappings and keeps W^X for all file types.

Microdroid's images (bootloader, boot.img, vendor_boot.img, super.img, vbmeta.img) ship in the Virtualization APEX. VirtualizationService combines them into a composite disk and adds a payload partition set backed by the app's APK and APEXes, plus an encrypted instance partition holding per instance verified boot data: a salt, trusted APEX public keys and rollback counters.

Device boot: placing pvmfw

AOSP lists the steps added to a pKVM device's boot:

  1. The Android Bootloader (ABL) loads pvmfw from its partition and verifies it.
  2. ABL gets its DICE secrets (CDIs and certificate chain) from a root of trust.
  3. ABL derives CDIs for pvmfw and appends them to the pvmfw binary.
  4. ABL adds a linux,pkvm-guest-firmware-memory reserved memory node to the device tree.
  5. ABL hands control to Linux, which initializes pKVM.
  6. pKVM unmaps that region from the host and protects it until power off.

The pvmfw README adds that the partition follows the boot image header format and that device specific configuration data sits at the next 4 KiB boundary after the binary, starting with magic 0x666d7670, so one centrally signed pvmfw binary can serve many devices. pvmfw is updated over the air.

pVM boot: pvmfw as the VM's boot ROM

The VMM may set only registers x0 to x14 of the primary vCPU and none on secondaries. The hypervisor hands the primary vCPU to pvmfw first, and the host cannot skip that. pvmfw trusts nothing the VMM set up: it validates the AVB signature on the loaded kernel or bootloader, builds a trusted device tree, derives the guest's DICE secrets, wipes its own secrets and jumps to the payload. Any failure triggers a PSCI SYSTEM_RESET. Instance details persist in the instance disk, encrypted with pvmfw's secret, so secrets go only to the same instance after reboot.

Microdroid boot, step by step

  1. pvmfw checks the bootloader comes from Google or an OEM. On first boot it stores the bootloader identity in the encrypted instance image; later boots refuse a changed identity.
  2. The bootloader verifies vbmeta and chained partitions such as boot and super, and derives the next stage secrets.
  3. The kernel mounts super (already verified) with logical partitions on dm-verity, and starts init.
  4. Microdroid Manager decrypts the instance image and reads the public keys and rollback counters for the trusted APK and APEXes.
  5. apexd mounts APEXes from virtual block devices.
  6. zipfuse mounts the APK, passed as a dm-verity block device; its config lists the requested APEXes.
  7. The payload runs. Microdroid Manager reports to VirtualizationService over Binder RPC and executes the main binary named in the APK config.

The resulting guarantees, from AOSP: Microdroid will not boot if boot.img, super.img, vbmeta.img or vbmeta_system.img fail verification, if the APK or any APEX fails, or for the same instance if the APK was updated. A modified instance image means no boot or a clean state. Unsigned changes to shared images cause I/O errors. One documented gap: Microdroid's encrypted storage has no rollback protection per encryption block, and a tampered block reads as garbage rather than an explicit I/O error, so payload storage formats should detect corruption themselves.

Files, keys and Binder

AuthFS brings Android's file descriptor passing across the boundary. The host's fd_server serves files as input or output; for input, the pVM checks content against a known hash with a Merkle tree, and for output it keeps its own hash tree. pVMs get a stable sealing key for persistent data and an attestation key. Binder was rewritten to run over sockets, so existing AIDL interfaces work: the payload creates an RpcServer, the host connects with an RpcSession. Each VM has a 32 bit CID that works like an IP address for vsock.

How does attestation of a protected VM work, and how does it relate to TCG DICE?

DICE in one paragraph

In the Trusted Computing Group's Device Identifier Composition Engine (DICE), when hardware hands over to the first software, a small engine mixes a Unique Device Secret (UDS) with a measurement of that software to produce a Compound Device Identifier (CDI), then locks the UDS away. Each later stage repeats this with its own CDI. Change any code and every later CDI changes. Google's Open Profile for DICE, which Android uses, derives separate attestation and sealing CDIs and issues a certificate at each step, with the UDS public key certified externally at manufacturing.

The pVM DICE chain

The AVF source describes the pVM DICE chain as a linked certificate chain rooted in ROM covering every component that loads and boots the VM:

SegmentBuilt byMust measure
ROM to pvmfw loader (such as ABL)Device vendorpvmfw, the hypervisor and other code relevant to pvmfw's secure execution
pvmfw onwardpvmfw, then MicrodroidVM bootloader, kernel, APK and APEXes

Node key pairs derive from CDI_Attest with HKDF SHA-512 and, today, Ed25519, per that document. AOSP adds that the attestation key pair can change between boots while a sealing secret stays stable; derive sealing keys from it and destroy it early. Each stage passes the next a deterministically encoded CBOR object with secrets and the chain. pvmfw and Microdroid extend the chain but do not fully validate its ROM rooted origin. That is remote attestation's job.

VM remote attestation

The design uses a small intermediate VM, the RKP VM:

  1. The RKP server attests the RKP VM, comparing the root public key of its DICE chain with keys in the RKP database and checking for RKP VM markers in the certificates.
  2. The RKP VM attests the pVM, comparing the pVM's DICE chain with its own and certifying the payload. Only Microdroid VMs are supported currently.

A payload calls AVmPayload_requestAttestation(challenge). On success it gets an RKP backed certificate chain and an attested private key known only to the pVM. The leaf carries an extension with OID 1.3.6.1.4.1.11129.2.1.29.1:

AttestationExtension ::= SEQUENCE {
    attestationChallenge       OCTET_STRING,
    isVmSecure                 BOOLEAN,
    vmComponents               SEQUENCE OF VmComponent,
}
VmComponent ::= SEQUENCE {
    name               UTF8String,
    securityVersion    INTEGER,
    codeHash           OCTET STRING,
    authorityHash      OCTET STRING,
}

The challenge proves freshness. isVmSecure is true only when every DICE certificate in the chain is in normal mode, so a debuggable VM shows up. vmComponents lists every APK and APEX loaded, with security version, code hash and signing authority hash.

The marker rule is neat. Vendors include an RKP VM marker from early boot in the TEE to the leaf before pvmfw, and pvmfw adds one when launching an RKP VM. A malicious guest's chain lacks continuous markers and is rejected. The feature is on by default but device builders can disable it at build time (PRODUCT_AVF_REMOTE_ATTESTATION_DISABLED) or boot time (avf.remote_attestation.enabled set to 0), so a relying party must handle its absence.

Worked example: isolated compilation

When a Mainline APEX update changes the boot classpath, Android must recompile boot classpath and system server JARs. Doing it at early boot is slow; doing it in normal Android before reboot means trusting a possibly compromised OS with code that later runs with high privilege. The com.android.compos APEX compiles in a pVM before reboot. AOSP's goal: Android as an untrusted client can only make compilation fail, and then Android falls back to boot time compilation.

  • The VM's signing key derives from its DICE profile: the mounted APEXes and APKs plus parameters such as debuggability.
  • Android boots the VM at early boot after each APEX update to check the expected public key.
  • Every input is checked with fs-verity, and its root hash must come in an APK that contributes to the VM's DICE profile.
  • Output integrity is tracked inside the VM, which signs the result only if the whole compilation succeeded.

AOSP's lesson applies to every payload: any API a VM exposes is attack surface, and all input from Android must be verified before use.

Which workloads use AVF today?

AOSP's use cases page lists these:

WorkloadVM typeWhat the VM protects
Isolated compilation (com.android.compos)ProtectedCompiled boot classpath and system server code after APEX updates; optional component
Content Safety On-device for Play Protect live threat detectionProtectedClassification models and encrypted protections; select devices with both features
Linux development environment (Terminal app)Non protectedIsolation of a Debian based image from Android; select devices
Device maker custom usesVariesAOSP gives an on device risk control example

The content safety flow is attestation in production. Private Compute Services starts the VM, gets its public key, hands ownership to live threat detection and sends the attestation and key to a server. The server verifies the attestation, encrypts protections with the VM's key and returns them; only the VM can decrypt them. AOSP says this resists reverse engineering even on rooted devices.

The Linux development environment is the contrast. Enabled in developer options, a Terminal app downloads a slightly modified Debian based image from a Google server and AVF boots it in a non protected VM; a guest agent reports state, ttyd serves a terminal to a WebView, and Android's tethering manager provides networking. The goal is isolation and convenience, not hiding data from the host.

Key and identity services and third party SDK isolation are often mentioned as candidates, but the AOSP use cases page does not list them as shipped, so we do not claim them.

TrustZone TEE, pKVM protected VM and the app sandbox compared

DimensionTrustZone TEEpKVM protected VMAndroid app sandbox
Isolation boundarySecure versus non secure state, enforced by EL3 and secure world softwareStage 2 page tables and IOMMU controlled by the EL2 hypervisorProcesses, UIDs, SELinux and stage 1 tables managed by the kernel
Survives a compromised Android kernelYesYes, for confidentiality and integrity, not availabilityNo
Isolated domainsOne secure world shared by trusted appsMany, created on demandOne per app
Who can load codeDevice maker and SoC vendor through secure bootImages signed by Google or the device vendor; payload APK and APEXes verified; only platform signed apps may request pVMsAny installed app
Update pathFirmware updates from the device makerpKVM in GKI with the kernel; pvmfw partition by OTA; Microdroid and AVF userspace in the com.android.virt APEXApp stores
Programming environmentVendor specific TEE APIsBionic, a subset of the NDK, Binder over vsockFull Android SDK and NDK
AttestationKey attestation through KeyMintDICE chain plus RKP backed VM remote attestationRelies on the TEE's key attestation

How to choose: keep ordinary app code in the sandbox. Keep small, hardware bound functions, and anything the SoC treats as secure only, in the TEE. Consider a protected VM when you need a richer environment than a TEE and protection from a compromised Android kernel, and can accept no UI, no HALs and host controlled availability. For a cross platform mirror, see our post on Windows virtualization based security and VBS enclaves.

Step by step: check support, run a Microdroid VM, and inspect its attestation

These steps come from AOSP's "Try AVF" page, the AVF getting started guide and the AVF debugging README. Use a test device, not one holding data you care about.

Step 1: know which devices are supported

The getting started guide lists supported AOSP targets: specific Google reference devices from the Pixel 6 generation onward, plus Cuttlefish (aosp_cf_x86_64_phone). Cuttlefish does not support protected VMs, only non protected ones. Some early reference devices ship AVF disabled and need Android 14, then pKVM enabled from an unlocked bootloader.

Step 2: check what the device has

These commands only read state.

# Confirm which device you are talking to
adb devices -l

# Protected VMs need ARM64
adb shell getprop ro.product.cpu.abi

# Is the AVF APEX present? The vm tool lives here.
adb shell ls /apex/com.android.virt/bin

# List hypervisor related system properties the device exposes
adb shell getprop | grep -i hypervisor

If the APEX directory is missing, the device does not ship AVF. The cited AOSP pages do not document one supported flag, so treat property output as a hint and confirm with the tests in step 4.

Step 3 (only if needed): enable pKVM on an early reference device

Warning: fastboot flashing unlock wipes all user data, and AOSP says an unlocked device is not trusted to uphold pVM security. Use only a dedicated test device, and first confirm exactly one device is connected and it is the one you mean to wipe.

# Check: exactly one device, and the serial is your test device
adb devices -l
adb reboot bootloader
fastboot devices

# Destructive: unlocking erases user data
fastboot flashing unlock
fastboot oem pkvm enable
fastboot reboot

Step 4: run the AVF tests

From an AOSP checkout:

source build/envsetup.sh
atest MicrodroidHostTestCases
atest MicrodroidTestApp

On failure, inspect the host_log_*.zip that atest names; it holds command output and VM logs.

Step 5: start a protected Microdroid VM

The getting started guide starts Microdroid with an empty payload in protected mode and attaches an adb shell:

packages/modules/Virtualization/vm/vm_shell.sh start-microdroid --auto-connect -- --protected

The log shows crosvm starting, the "pVM firmware" banner, block devices found, "Starting payload...", and adbd listening on vsock port 5555 inside the VM. On the device, the vm tool works directly:

adb shell /apex/com.android.virt/bin/vm run-microdroid --debug none
adb shell /apex/com.android.virt/bin/vm run-microdroid --dump-device-tree /data/local/tmp/vm.dtb

Mind the debug level. The README says full debugging is the default when the option is omitted, and that a debuggable protected VM "introduces many loopholes" that can nullify the hypervisor's protection. Set none explicitly for anything production like; attestation exposes a debuggable VM through isVmSecure.

Step 6: run the sample app

TARGET_BUILD_APPS=MicrodroidDemoApp m apps_only dist
adb install -t out/dist/MicrodroidDemoApp.apk
adb shell pm grant com.android.microdroid.demo android.permission.MANAGE_VIRTUAL_MACHINE

AOSP notes this demo works only on Cuttlefish. Your own app follows the "Write an AVF app" page: the host side builds a VirtualMachineConfig from assets/vm_config.json, calls VirtualMachineManager.getOrCreate, and in onPayloadReady connects to the VM's Binder server over vsock. The pVM side is a native library whose android_native_main starts the Binder service:

{
  "os": { "name": "microdroid" },
  "task": {
    "type": "microdroid_launcher",
    "command": "MicrodroidTestNativeLib.so"
  }
}

Step 7: read the attestation chain

In the payload, call AVmPayload_requestAttestation with a fresh challenge from your server; AOSP points to VmAttestationDemoApp in the AVF tree as the example. On the verifier, inspect and verify the returned chain:

openssl x509 -in leaf.pem -noout -text
openssl x509 -in intermediate.pem -noout -subject -issuer
openssl verify -CAfile rkp_root.pem -untrusted intermediate.pem leaf.pem

In the leaf, decode extension 1.3.6.1.4.1.11129.2.1.29.1 against the ASN.1 above and check that the challenge matches, isVmSecure is true, and every vmComponents entry has the code hash, authority hash and security version you expect. To check the DICE handover on a device, the pVM DICE chain document names the test MicrodroidTests#protectedVmHasValidDiceChain, which reads the chain from a protected Microdroid VM and uses the hwtrust library to confirm it follows the Android Profile for DICE and that each certificate verifies the next.

Common mistakes

  • Assuming every Android device supports protected VMs. AVF needs ARM64, pKVM, an IOMMU for every DMA device, a pvmfw capable bootloader and SoC requirements. Cuttlefish and x86_64 run only non protected VMs. Check capability at runtime and keep a fallback.
  • Treating a pVM as a TEE replacement for every job. AOSP says AVF does not fully replace TrustZone, and a pVM has no availability guarantee.
  • Shipping a debuggable VM. The vm tool defaults to full debug; set none and verify through attestation.
  • Trusting data that crossed the boundary. pKVM protects memory, not logic. Anything from the host through Binder, AuthFS or shared buffers is attacker controlled if the host is compromised. Keep the exposed API small.
  • Sharing more than you meant to. Sharing is page granular; use bounce buffers and register MMIO regions only where needed.
  • Ignoring unlock state. An unlocked bootloader lets pvmfw and pKVM be replaced; servers should check verified boot state, not only the DICE chain.
  • Reading upstream kernel status as Android status. Upstream marks pKVM experimental with DMA isolation and pvmfw unimplemented; Android's kernel carries more.
  • Not tracking the guest as its own software. Microdroid is a bootloader, kernel, userspace and APEXes, and your payload is an APK with native libraries. Each has versions and vulnerabilities. Teams often track the host app and forget the payload.

Where Safeguard fits, honestly

Safeguard does not analyze hypervisors, firmware, bootloaders or device hardware, does not manage devices, and does not verify DICE chains or attestation certificates. pKVM, pvmfw and Microdroid fixes arrive through Android updates from Google and the device maker.

Where Safeguard helps is the software you build on top. An AVF app is two programs, the host app and the payload that runs in Microdroid, and both pull in open source dependencies, often native C, C++ or Rust libraries; your verifier service adds certificate and ASN.1 parsing libraries. Safeguard scans repositories, container images and SBOM files (safeguard scan --dir ., or an image or SBOM), matches components against vulnerability databases, shows which projects contain a given component and version, applies reachability analysis and enforces policies and gates. How much reachability narrows a list depends on the codebase, so measure it during evaluation. Treat the payload as its own project with its own SBOM, so a vulnerable library inside the VM does not hide behind the host app's clean report.

FAQ

What Android version introduced the Android Virtualization Framework?

Android 13, according to AOSP's "Why AVF?" page. VM remote attestation became strongly recommended from Android 15.

Is pKVM the same as KVM?

pKVM is built on Linux KVM. It extends KVM's EL2 component so the hypervisor can restrict the host, keep stage 2 on for the host and isolate guests marked protected. Upstream Linux enables it with kvm-arm.mode=protected and still calls it experimental; Android's kernel carries more of it.

Can a rooted or compromised Android kernel read a protected VM's memory?

No, by design. Donated pages leave the host's stage 2 mappings, DMA is blocked by the IOMMU, and SMCs are proxied. The host can still stop or starve the VM. An unlocked bootloader is different, because pKVM itself can then be replaced.

What is the difference between Microdroid and regular Android?

Microdroid keeps Bionic, a subset of the NDK, Verified Boot, SELinux, Binder over vsock and debugging tools, and drops the Java framework, SystemServer, Zygote, graphics and HALs. It runs one payload from an APK.

Does AVF replace TrustZone?

No. AOSP says Android SoCs cannot function without TrustZone, and pKVM proxies the host's calls into it.

Can third party apps create protected VMs?

AOSP's security page says only apps signed with the platform key can request permission to create or interact with pVMs, and pVM images must be signed by Google or the device vendor.

What is pvmfw?

The first code in every protected VM, loaded by the hypervisor from memory the host cannot touch. It verifies the guest's AVB signature, builds a trusted device tree, derives DICE secrets, and resets the VM on any failure.

Does a protected VM protect against the device maker?

No. AOSP says actors in the device supply chain, such as device makers and SoC vendors, are necessarily trusted.

Can I try protected VMs on an emulator?

No. Cuttlefish and x86_64 support non protected VMs only. Protected VMs need a supported ARM64 device.

Protected VMs are one more place your code, and the open source inside it, runs. The payload is rebuilt with each app release, and its native libraries and your attestation verifier carry the same dependency risk as any other project.

Fix it without waiting for upstream

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation categories include dependencies, licenses, security posture and findings, and each one is set separately. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds.

3. Gold Registry: start from components that are already fixed

Gold Registry provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. Ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingSafeguard policies and gates in CI
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

The first demo is a real Safeguard CLI session: install, open the interactive terminal, and ask it to fix a lodash CVE. It reads the finding and advisory, asks before any command that changes something, edits package.json, runs install and tests, and pushes nothing. The same flow fits the host app or verifier service around a pVM payload.

Click through it at your own pace, or open it full screen.

The second demo sets up the Safeguard runner on your own machine, approves it with a device code and scans from the terminal. That suits the build host where your payload's native libraries are compiled, since the scan runs where the code already is.

Click through it at your own pace, or open it full screen.

The third demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. Your team can then ask which projects, including a pVM payload project, carry a given component version.

Click through it at your own pace, or open it full screen.

To try it on your own projects, download Safeguard or read the CLI docs.

Quick check

If a compromised Android kernel cannot read a protected VM's memory, what can it still do to that VM?

It can deny availability. The host schedules the VM's vCPUs, handles physical interrupts and allocates memory through the VMM, so it can starve or stop the VM. pKVM guarantees confidentiality and integrity, not availability.

Which field in a protected VM's attestation certificate reveals that the VM was started in debuggable mode?

The isVmSecure field in the attestation extension. It is true only when every DICE certificate in the pVM's chain is in normal mode, so a debuggable VM reports false.

Sources

Last reviewed: 25 October 2026. AVF changes with each Android release; check the linked AOSP pages and AVF source docs for current behavior before you build on it.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.