Restrict access to certain vm_payload APIs
Require the USE_CUSTOM_VIRTUAL_MACHINE permission in order to use
certain APIs from the VM payload that should not be exposed to all
clients of the AVF API. The permission is inferred from the use of a VM
config file, which requires the permission. The permission is only
granted to platform and test components.
Use this new ability to prevent VM payloads from accessing the raw DICE
chain and attestation CDI.
Fix: 243514248
Test: atest MicrodroidTests ComposHostTestCases
Change-Id: I1fd65ee1d0f624bc3ff9143f597e455c84ed2b02
diff --git a/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl b/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
index d3ebe5c..4dd3db6 100644
--- a/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
+++ b/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
@@ -39,18 +39,23 @@
/**
* Gets the DICE attestation chain for the VM.
*
- * STOPSHIP:
- * TODO: don't expose this to untrusted payloads as it contains privacy breaking identifiers.
+ * The DICE chain must not be made available to all VMs as it contains privacy breaking
+ * identifiers.
+ *
+ * @return the VM's raw DICE certificate chain.
+ * @throws SecurityException if the use of test APIs is not permitted.
*/
byte[] getDiceAttestationChain();
/**
* Gets the DICE attestation CDI for the VM.
*
- * STOPSHIP:
- * TODO: A better API would handle key derivation on behalf of the payload so they can't forget
- * to do it themselves. It also means the payload doesn't get the raw CDI so there's less chance
- * of it leaking.
+ * The raw attestation CDI isn't very useful but is used for smoke tests. A better API would
+ * handle key derivation on behalf of the payload so they can't forget to do it themselves and
+ * would also mean the payload doesn't get the raw CDI which reduces the chance of it leaking.
+ *
+ * @return the VM's raw attestation CDI.
+ * @throws SecurityException if the use of test APIs is not permitted.
*/
byte[] getDiceAttestationCdi();
}
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 748b497..00c3dce 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -404,6 +404,13 @@
)
.context("Failed to run zipfuse")?;
+ // Restricted APIs are only allowed to be used by platform or test components. Infer this from
+ // the use of a VM config file since those can only be used by platform and test components.
+ let allow_restricted_apis = match payload_metadata {
+ PayloadMetadata::config_path(_) => true,
+ PayloadMetadata::config(_) => false,
+ };
+
let config = load_config(payload_metadata).context("Failed to load payload metadata")?;
let task = config
@@ -439,7 +446,7 @@
// Wait until zipfuse has mounted the APK so we can access the payload
wait_for_property_true(APK_MOUNT_DONE_PROP).context("Failed waiting for APK mount done")?;
- register_vm_payload_service(service.clone(), dice)?;
+ register_vm_payload_service(allow_restricted_apis, service.clone(), dice)?;
ProcessState::start_thread_pool();
system_properties::write("dev.bootcomplete", "1").context("set dev.bootcomplete")?;
diff --git a/microdroid_manager/src/vm_payload_service.rs b/microdroid_manager/src/vm_payload_service.rs
index 4b47ad9..159bf67 100644
--- a/microdroid_manager/src/vm_payload_service.rs
+++ b/microdroid_manager/src/vm_payload_service.rs
@@ -26,6 +26,7 @@
/// Implementation of `IVmPayloadService`.
struct VmPayloadService {
+ allow_restricted_apis: bool,
virtual_machine_service: Strong<dyn IVirtualMachineService>,
dice: DiceContext,
}
@@ -54,10 +55,12 @@
}
fn getDiceAttestationChain(&self) -> binder::Result<Vec<u8>> {
+ self.check_restricted_apis_allowed()?;
Ok(self.dice.bcc.clone())
}
fn getDiceAttestationCdi(&self) -> binder::Result<Vec<u8>> {
+ self.check_restricted_apis_allowed()?;
Ok(self.dice.cdi_attest.to_vec())
}
}
@@ -66,18 +69,32 @@
impl VmPayloadService {
/// Creates a new `VmPayloadService` instance from the `IVirtualMachineService` reference.
- fn new(vm_service: Strong<dyn IVirtualMachineService>, dice: DiceContext) -> Self {
- Self { virtual_machine_service: vm_service, dice }
+ fn new(
+ allow_restricted_apis: bool,
+ vm_service: Strong<dyn IVirtualMachineService>,
+ dice: DiceContext,
+ ) -> Self {
+ Self { allow_restricted_apis, virtual_machine_service: vm_service, dice }
+ }
+
+ fn check_restricted_apis_allowed(&self) -> binder::Result<()> {
+ if self.allow_restricted_apis {
+ Ok(())
+ } else {
+ error!("Use of restricted APIs is not allowed");
+ Err(Status::new_exception_str(ExceptionCode::SECURITY, Some("Use of restricted APIs")))
+ }
}
}
/// Registers the `IVmPayloadService` service.
pub(crate) fn register_vm_payload_service(
+ allow_restricted_apis: bool,
vm_service: Strong<dyn IVirtualMachineService>,
dice: DiceContext,
) -> Result<()> {
let vm_payload_binder = BnVmPayloadService::new_binder(
- VmPayloadService::new(vm_service, dice),
+ VmPayloadService::new(allow_restricted_apis, vm_service, dice),
BinderFeatures::default(),
);
add_service(VM_PAYLOAD_SERVICE_NAME, vm_payload_binder.as_binder())