Report DICE policy errors with the PAYLOAD_CHANGED error code
When a DICE policy error occurs, it indicates that the payload has
changed in an incompatible way. That might mean the version has
downgraded, or more/fewer components are present, etc but the result is
that the VM will not be able to access its previous secrets. This is an
event that the client app needs to notice and handle so it needs to be
exposed better than an UNKNOWN error.
There's already a PAYLOAD_CHANGED that was used when strict version
binding was the only option and no upgrade of VM payloads was allowed.
This has become unused for updatable VMs but feels appropriate to make
use of again when the change to the payload was illegal, as identified
by the DICE policy error.
Bug: 420367677
Test: atest MicrodroidTests
Flag: EXEMPT bugfix
Change-Id: Icc09930277de0911528c5fd4a9c640623553125a
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationcommon/ErrorCode.aidl b/android/virtualizationservice/aidl/android/system/virtualizationcommon/ErrorCode.aidl
index cf1e251..9b39bc0 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationcommon/ErrorCode.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationcommon/ErrorCode.aidl
@@ -32,7 +32,8 @@
PAYLOAD_VERIFICATION_FAILED = 1,
/**
- * Error code indicating that the payload is verified, but has changed since the last boot.
+ * Error code indicating that the payload is verified, but has changed to be incompatible with
+ * the previous payload. This payload has not been allowed to boot to protect the VM's data.
*/
PAYLOAD_CHANGED = 2,
diff --git a/guest/microdroid_manager/src/vm_secret.rs b/guest/microdroid_manager/src/vm_secret.rs
index e7d4740..2313f6e 100644
--- a/guest/microdroid_manager/src/vm_secret.rs
+++ b/guest/microdroid_manager/src/vm_secret.rs
@@ -370,10 +370,14 @@
} else {
let error =
SecretkeeperError::deserialize_from_packet(get_response).map_err(anyhow_err)?;
- if *error == SecretkeeperError::EntryNotFound {
- return Ok(None);
+ match *error {
+ SecretkeeperError::EntryNotFound => Ok(None),
+ SecretkeeperError::DicePolicyError => {
+ Err(super::MicrodroidError::PayloadChanged("Dice policy error".to_string())
+ .into())
+ }
+ _ => Err(anyhow!("Secretkeeper get failed: {error:?}")),
}
- Err(anyhow!("Secretkeeper get failed: {error:?}"))
}
}
}
diff --git a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineCallback.java b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineCallback.java
index b077826..d3f4aed 100644
--- a/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineCallback.java
+++ b/libs/framework-virtualization/src/android/system/virtualmachine/VirtualMachineCallback.java
@@ -54,7 +54,10 @@
*/
int ERROR_PAYLOAD_VERIFICATION_FAILED = 1;
- /** Error code indicating that the payload is verified, but has changed since the last boot. */
+ /**
+ * Error code indicating that the payload is verified, but has changed to be incompatible with
+ * the previous payload. This payload has not been allowed to boot to protect the VM's data.
+ */
int ERROR_PAYLOAD_CHANGED = 2;
/** Error code indicating that the payload config is invalid. */
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index 540ae81..640ac4d 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -3128,9 +3128,7 @@
// Now pVM shouldn't boot.
BootResult bootResult = tryBootVm(TAG, vm);
assertThat(bootResult.deathReason)
- .isEqualTo(
- // TODO(ioffe): this should probably be payload verification error?
- VirtualMachineCallback.STOP_REASON_MICRODROID_UNKNOWN_RUNTIME_ERROR);
+ .isEqualTo(VirtualMachineCallback.STOP_REASON_MICRODROID_PAYLOAD_HAS_CHANGED);
}
@Test