Merge "Update stub.c" into main
diff --git a/Android.bp b/Android.bp
index 2091a90..7cedfb7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -98,6 +98,7 @@
aconfig_declarations {
name: "avf_aconfig_flags",
package: "com.android.system.virtualmachine.flags",
+ container: "com.android.virt",
srcs: [
"avf_flags.aconfig",
],
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 5b0c000..58dcc06 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -43,6 +43,9 @@
},
{
"name": "libsecretkeeper_comm.test"
+ },
+ {
+ "name": "libdice_driver_test"
}
],
"avf-postsubmit": [
diff --git a/apex/manifest.json b/apex/manifest.json
index eac57c3..b32aa7b 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,4 +1,8 @@
{
"name": "com.android.virt",
- "version": 2
+ "version": 2,
+ "requireNativeLibs": [
+ "libEGL.so",
+ "libGLESv2.so"
+ ]
}
diff --git a/avf_flags.aconfig b/avf_flags.aconfig
index 589d227..a5260a9 100644
--- a/avf_flags.aconfig
+++ b/avf_flags.aconfig
@@ -1,4 +1,5 @@
package: "com.android.system.virtualmachine.flags"
+container: "com.android.virt"
flag {
name: "avf_v_test_apis"
diff --git a/docs/updatable_vm.md b/docs/updatable_vm.md
index de5552e..ff1a0d6 100644
--- a/docs/updatable_vm.md
+++ b/docs/updatable_vm.md
@@ -1,3 +1,99 @@
# Updatable VM
-(To be filled)
+From Android V+, AVF (with Microdroid) supports Updatable VMs. This allows the VM instances to
+remain stable even when the VM core components and payload are upgraded. This includes (but is not
+limited to) update of payload apk and Microdroid OS.
+
+## Background
+
+The following constructs have been used (and are critical) to support Updatable VM:
+
+1. [Secretkeeper][sk_project] is the critical piece of solution. It provides secure storage for VM's
+ secrets. It is specified as [a HAL][secretkeeperhal] and needs to be implemented in an
+ environment with privilege higher than protected VM.
+1. [DICE Policies][dice_policy]: DICE policy is the mechanism for setting constraints on a DICE
+ chain(i.e., identities of a VM). VM seals its secrets using DICE policies, and Secretkeeper
+ serves as a policy verifier.
+1. [AuthGraph key exchange][authgraphke]: The requests/responses between pVM and Secretkeeper are
+ ferried via Android (which is untrusted). A cryptographically secure channel is setup using
+ AuthGraph key exchange.
+
+## VmSecrets::V2
+
+Updatable VMs are achieved by changing Microdroid's secret management. It now supports
+`VmSecrets::V2` which is derived from 2 independently secured secrets:
+
+1. Secretkeeper protected secret: This is random 64 bytes generated by VM on first boot & stored in
+ Secretkeeper.
+1. DICE Sealing CDIs (similar to legacy secrets V1): These are defined by
+ [Open Profile for DICE][open_dice_spec_cdi] and must remain the same across software updates.
+
+Secretkeeper protected secret is protected against rollback of boot images i.e. VM instance rebooted
+with downgraded images will not have access to these secrets. This is done using
+[Policy Gated Storage feature](policy_gated_storage) of Secretkeeper. On the first boot of the VM
+instance, Microdroid Manager (on behalf of the VM payload) generates a secret, stores it in
+Secretkeeper and on further reboots, this is retrieved from it. Along with this secret, a
+[sealing policy](#sealing-policy) is also stored (in Secretkeeper) that ensures that secrets are not
+released to the VM instance booted with downgraded images.
+
+Each Secretkeeper client needs a 64 bytes' Id to store an entry in Secretkeeper. For Microdroid,
+this is Instance Id. It is allocated by host (when the VM instance is created) and relayed to VM via a property (`instance-id`)
+in device tree node (`/avf/untrusted`)
+
+## Sealing Policy
+
+Sealing Policy is a DICE policy on the DICE chain of the payload running in Microdroid. This is
+constructed by Microdroid Manager on behalf of the payload and is stored along with the secret.
+
+A highly simplified view - Sealing policy built by Microdroid has the following constraints:
+
+- ExactMatch on DiceCertChainInitialPayload (root public key)
+- ExactMatch of Instance salt, this is present in DiceChainEntry corresponding to OS (and is derived
+ deterministically from Instance Id). This is needed to prevent the secrets of one instance from
+ being accessible to another instance running with the same VM images.
+- For each DiceChainEntry:
+ 1. ExactMatch on AUTHORITY_HASH.
+ 1. ExactMatch on MODE - Secret should be inaccessible if any of the runtime
+ configuration changes. For example, the secrets stored with a boot stage being in Normal mode
+ should be inaccessible when the same stage is booted in Debug mode.
+ 1. GreaterOrEqual on SECURITY_VERSION: The secrets will be accessible if version of any
+ image is greater or equal to the set version.
+- For each Subcomponent on the last DiceChainEntry (which corresponds to VM payload, See
+ [vm_config.cddl][vm_config_cddl]): - GreaterOrEqual on SECURITY_VERSION - ExactMatch on
+ AUTHORITY_HASH.
+
+The sealing policy is updated each time the secret is retrieved. This ensures the secrets are only
+released if the security version of the images are non-decreasing.
+
+## Deferring rollback protection
+
+Traditionally in Android, each boot stage is responsible for rollback protection of the next boot
+image. ABL has access to tamper evident storage to ensure that. VM (Android U and lower) use
+instance.img where the boot stages (pvmfw/Microdroid) would store information about packages they
+boot (exact code_hash) and on subsequent boot of the instance ensure that the same images are
+allowed to run. This prevented running of older images, but also prevented running newer images and
+hence VMs were not updatable.
+
+Secretkeeper HAL then introduced the capability of storing secrets in a TA such that the owner of
+the secret ( for ex. VM) while storing it, includes a corresponding sealing policy such that only
+entities with DICE chain that adheres to those policies can access the secrets.
+
+This allows the bootloaders to defer rollback protection to the payload. Host relays this intention
+to pVM (both pVM firmware and OS) using the property (`defer-rollback-protection`) in device tree
+node (`/avf/untrusted`). If this is set and the guest OS is capable of `SecretkeeperProtection` then
+VMs use Secretkeeper based rollback protection.
+
+### Note on legacy support
+
+If the device does not support Secretkeeper, Microdroid will fallback to legacy secrets
+(`VmSecrets::V1`). These are not protected against the rollback of boot images and hence pVM
+firmware cannot defer rollback protection. Instance image is used to record information about the
+images on the first boot of the instance, and any further boot prevents any different image from
+running i.e, Updatable VMs are not supported.
+
+[authgraphke]: https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl
+[dice_policy]: https://android.googlesource.com/platform/system/secretkeeper/+/refs/heads/main/dice_policy/
+[open_dice_spec_cdi]: https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md#cdi-values
+[secretkeeperhal]: https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl
+[sk_project]: https://android.googlesource.com/platform/system/secretkeeper/
+[vm_config_cddl]: https://cs.android.com/android/platform/superproject/main/+/main:packages/modules/Virtualization/microdroid_manager/src/vm_config.cddl
diff --git a/java/framework/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java b/java/framework/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java
index 219fdca..7a4f564 100644
--- a/java/framework/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java
+++ b/java/framework/src/android/system/virtualmachine/VirtualMachineCustomImageConfig.java
@@ -107,7 +107,7 @@
}
}
}
- return null;
+ return builder.build();
}
PersistableBundle toPersistableBundle() {
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index e19a343..169ecae 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -343,9 +343,8 @@
},
}
-// TODO(ioffe): rename to microdroid_first_stage_ramdisk
android_filesystem {
- name: "microdroid_fstab_ramdisk",
+ name: "microdroid_first_stage_ramdisk",
deps: [
"microdroid_fstab",
],
diff --git a/microdroid/initrd/Android.bp b/microdroid/initrd/Android.bp
index ec971fa..544a3ff 100644
--- a/microdroid/initrd/Android.bp
+++ b/microdroid/initrd/Android.bp
@@ -34,7 +34,7 @@
name: "microdroid_initrd_gen",
srcs: [
":microdroid_ramdisk",
- ":microdroid_fstab_ramdisk",
+ ":microdroid_first_stage_ramdisk",
],
out: ["microdroid_initrd.img"],
cmd: "cat $(in) > $(out)",
@@ -44,7 +44,7 @@
name: "microdroid_gki-android14-6.1_initrd_gen_arm64",
srcs: [
":microdroid_ramdisk",
- ":microdroid_fstab_ramdisk",
+ ":microdroid_first_stage_ramdisk",
":microdroid_gki_modules-6.1-arm64",
],
out: ["microdroid_initrd.img"],
@@ -55,7 +55,7 @@
name: "microdroid_gki-android14-6.1_initrd_gen_x86_64",
srcs: [
":microdroid_ramdisk",
- ":microdroid_fstab_ramdisk",
+ ":microdroid_first_stage_ramdisk",
":microdroid_gki_modules-6.1-x86_64",
],
out: ["microdroid_initrd.img"],
diff --git a/pvmfw/avb/src/ops.rs b/pvmfw/avb/src/ops.rs
index 9711f72..62bf239 100644
--- a/pvmfw/avb/src/ops.rs
+++ b/pvmfw/avb/src/ops.rs
@@ -59,7 +59,7 @@
pub(crate) fn verify_partition(
&mut self,
partition_name: &CStr,
- ) -> SlotVerifyResult<SlotVerifyData> {
+ ) -> SlotVerifyResult<SlotVerifyData<'a>> {
slot_verify(
self,
&[partition_name],
@@ -70,7 +70,7 @@
}
}
-impl<'a> avb::Ops for Ops<'a> {
+impl<'a> avb::Ops<'a> for Ops<'a> {
fn read_from_partition(
&mut self,
partition: &CStr,
@@ -82,7 +82,7 @@
Ok(buffer.len())
}
- fn get_preloaded_partition(&mut self, partition: &CStr) -> IoResult<&[u8]> {
+ fn get_preloaded_partition(&mut self, partition: &CStr) -> IoResult<&'a [u8]> {
self.payload.get_partition(partition)
}
diff --git a/pvmfw/avb/src/verify.rs b/pvmfw/avb/src/verify.rs
index 2ebe9a1..038b1d6 100644
--- a/pvmfw/avb/src/verify.rs
+++ b/pvmfw/avb/src/verify.rs
@@ -280,11 +280,10 @@
}
let initrd = initrd.unwrap();
- let mut initrd_ops = Ops::new(&payload);
let (debug_level, initrd_descriptor) =
- if verify_initrd(&mut initrd_ops, PartitionName::InitrdNormal, initrd).is_ok() {
+ if verify_initrd(&mut ops, PartitionName::InitrdNormal, initrd).is_ok() {
(DebugLevel::None, hash_descriptors.initrd_normal)
- } else if verify_initrd(&mut initrd_ops, PartitionName::InitrdDebug, initrd).is_ok() {
+ } else if verify_initrd(&mut ops, PartitionName::InitrdDebug, initrd).is_ok() {
(DebugLevel::Full, hash_descriptors.initrd_debug)
} else {
return Err(SlotVerifyError::Verification(None).into());
diff --git a/service_vm/manager/src/lib.rs b/service_vm/manager/src/lib.rs
index c50f0b3..273b54d 100644
--- a/service_vm/manager/src/lib.rs
+++ b/service_vm/manager/src/lib.rs
@@ -277,6 +277,7 @@
}
let instance_img = OpenOptions::new()
.create(true)
+ .truncate(true)
.read(true)
.write(true)
.open(instance_img_path)
diff --git a/service_vm/test_apk/aidl/com/android/virt/vm_attestation/testservice/IAttestationService.aidl b/service_vm/test_apk/aidl/com/android/virt/vm_attestation/testservice/IAttestationService.aidl
index 18df572..b139d44 100644
--- a/service_vm/test_apk/aidl/com/android/virt/vm_attestation/testservice/IAttestationService.aidl
+++ b/service_vm/test_apk/aidl/com/android/virt/vm_attestation/testservice/IAttestationService.aidl
@@ -29,16 +29,16 @@
@Backing(type="int")
enum AttestationStatus {
/** The remote attestation completes successfully. */
- ATTESTATION_OK = 0,
+ OK = 0,
/** The challenge size is not between 0 and 64. */
- ATTESTATION_ERROR_INVALID_CHALLENGE = 1,
+ ERROR_INVALID_CHALLENGE = 1,
/** Failed to attest the VM. Please retry at a later time. */
- ATTESTATION_ERROR_ATTESTATION_FAILED = 2,
+ ERROR_ATTESTATION_FAILED = 2,
/** Remote attestation is not supported in the current environment. */
- ATTESTATION_ERROR_UNSUPPORTED = 3,
+ ERROR_UNSUPPORTED = 3,
}
/**
diff --git a/service_vm/test_apk/src/native/main.rs b/service_vm/test_apk/src/native/main.rs
index ff21bd8..00ddff8 100644
--- a/service_vm/test_apk/src/native/main.rs
+++ b/service_vm/test_apk/src/native/main.rs
@@ -113,7 +113,7 @@
};
let certificate_chain =
res.certificate_chain().with_log().or_service_specific_exception(-1)?;
- let status = AttestationStatus::ATTESTATION_OK;
+ let status = AttestationStatus::OK;
let signature = res.sign(message).with_log().or_service_specific_exception(-1)?;
Ok(SigningResult { certificateChain: certificate_chain, signature, status })
}
@@ -126,16 +126,14 @@
fn to_attestation_status(status: AVmAttestationStatus) -> AttestationStatus {
match status {
- AVmAttestationStatus::ATTESTATION_OK => AttestationStatus::ATTESTATION_OK,
+ AVmAttestationStatus::ATTESTATION_OK => AttestationStatus::OK,
AVmAttestationStatus::ATTESTATION_ERROR_INVALID_CHALLENGE => {
- AttestationStatus::ATTESTATION_ERROR_INVALID_CHALLENGE
+ AttestationStatus::ERROR_INVALID_CHALLENGE
}
AVmAttestationStatus::ATTESTATION_ERROR_ATTESTATION_FAILED => {
- AttestationStatus::ATTESTATION_ERROR_ATTESTATION_FAILED
+ AttestationStatus::ERROR_ATTESTATION_FAILED
}
- AVmAttestationStatus::ATTESTATION_ERROR_UNSUPPORTED => {
- AttestationStatus::ATTESTATION_ERROR_UNSUPPORTED
- }
+ AVmAttestationStatus::ATTESTATION_ERROR_UNSUPPORTED => AttestationStatus::ERROR_UNSUPPORTED,
}
}
diff --git a/tests/hostside/Android.bp b/tests/hostside/Android.bp
index 068d8f9..2eca2fa 100644
--- a/tests/hostside/Android.bp
+++ b/tests/hostside/Android.bp
@@ -23,6 +23,7 @@
per_testcase_directory: true,
data: [
":MicrodroidTestApp",
+ ":MicrodroidTestAppUpdated",
":microdroid_general_sepolicy.conf",
":test.com.android.virt.pem",
":test2.com.android.virt.pem",
diff --git a/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java b/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
index 007f38c..1e81172 100644
--- a/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
+++ b/tests/hostside/helper/java/com/android/microdroid/test/host/MicrodroidHostTestCaseBase.java
@@ -31,6 +31,7 @@
import com.android.tradefed.device.TestDevice;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.RunUtil;
@@ -49,12 +50,16 @@
public abstract class MicrodroidHostTestCaseBase extends BaseHostJUnit4Test {
protected static final String TEST_ROOT = "/data/local/tmp/virt/";
+ protected static final String TRADEFED_TEST_ROOT = "/data/local/tmp/virt/tradefed/";
protected static final String LOG_PATH = TEST_ROOT + "log.txt";
protected static final String CONSOLE_PATH = TEST_ROOT + "console.txt";
+ protected static final String TRADEFED_CONSOLE_PATH = TRADEFED_TEST_ROOT + "console.txt";
private static final int TEST_VM_ADB_PORT = 8000;
private static final String MICRODROID_SERIAL = "localhost:" + TEST_VM_ADB_PORT;
private static final String INSTANCE_IMG = "instance.img";
protected static final String VIRT_APEX = "/apex/com.android.virt/";
+ protected static final String SECRETKEEPER_AIDL =
+ "android.hardware.security.secretkeeper.ISecretkeeper/default";
private static final long MICRODROID_ADB_CONNECT_TIMEOUT_MINUTES = 5;
protected static final long MICRODROID_COMMAND_TIMEOUT_MILLIS = 30000;
@@ -244,6 +249,17 @@
return ret;
}
+ public boolean isUpdatableVmSupported() throws DeviceNotAvailableException {
+ // Updatable VMs are possible iff device supports Secretkeeper.
+ CommandRunner android = new CommandRunner(getDevice());
+ CommandResult result = android.runForResult("service check", SECRETKEEPER_AIDL);
+ assertWithMessage("Failed to run service check. Result= " + result)
+ .that(result.getStatus() == CommandStatus.SUCCESS && result.getExitCode() == 0)
+ .isTrue();
+ boolean is_sk_supported = !result.getStdout().trim().contains("not found");
+ return is_sk_supported;
+ }
+
public List<String> getSupportedOSList() throws Exception {
return parseStringArrayFieldsFromVmInfo("Available OS list: ");
}
diff --git a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
index 06806ec..2b53571 100644
--- a/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
+++ b/tests/hostside/java/com/android/microdroid/test/MicrodroidHostTests.java
@@ -19,12 +19,14 @@
import static com.android.microdroid.test.host.CommandResultSubject.command_results;
import static com.android.tradefed.device.TestDevice.MicrodroidBuilder;
import static com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestLogData;
+import com.android.tradefed.device.DeviceRuntimeException;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
@@ -88,9 +90,12 @@
@UseParametersRunnerFactory(DeviceJUnit4ClassRunnerWithParameters.RunnerFactory.class)
public class MicrodroidHostTests extends MicrodroidHostTestCaseBase {
private static final String APK_NAME = "MicrodroidTestApp.apk";
+ private static final String APK_UPDATED_NAME = "MicrodroidTestAppUpdated.apk";
private static final String PACKAGE_NAME = "com.android.microdroid.test";
private static final String SHELL_PACKAGE_NAME = "com.android.shell";
private static final String VIRT_APEX = "/apex/com.android.virt/";
+ private static final String INSTANCE_IMG = TEST_ROOT + "instance.img";
+ private static final String INSTANCE_ID_FILE = TEST_ROOT + "instance_id";
private static final int MIN_MEM_ARM64 = 170;
private static final int MIN_MEM_X86_64 = 196;
@@ -409,6 +414,67 @@
}
@Test
+ @CddTest
+ public void UpgradedPackageIsAcceptedWithSecretkeeper() throws Exception {
+ assumeUpdatableVmSupported();
+ getDevice().uninstallPackage(PACKAGE_NAME);
+ getDevice().installPackage(findTestFile(APK_NAME), /* reinstall= */ true);
+ ensureMicrodroidBootsSuccessfully(INSTANCE_ID_FILE, INSTANCE_IMG);
+
+ getDevice().uninstallPackage(PACKAGE_NAME);
+ cleanUpVirtualizationTestSetup(getDevice());
+ // Install the updated version of app (versionCode 6)
+ getDevice().installPackage(findTestFile(APK_UPDATED_NAME), /* reinstall= */ true);
+ ensureMicrodroidBootsSuccessfully(INSTANCE_ID_FILE, INSTANCE_IMG);
+ }
+
+ @Test
+ @CddTest
+ public void DowngradedPackageIsRejectedProtectedVm() throws Exception {
+ assumeProtectedVm(); // Rollback protection is provided only for protected VM.
+
+ // Install the upgraded version (v6)
+ getDevice().uninstallPackage(PACKAGE_NAME);
+ getDevice().installPackage(findTestFile(APK_UPDATED_NAME), /* reinstall= */ true);
+ ensureMicrodroidBootsSuccessfully(INSTANCE_ID_FILE, INSTANCE_IMG);
+
+ getDevice().uninstallPackage(PACKAGE_NAME);
+ cleanUpVirtualizationTestSetup(getDevice());
+ // Install the older version (v5)
+ getDevice().installPackage(findTestFile(APK_NAME), /* reinstall= */ true);
+
+ assertThrows(
+ "pVM must fail to boot with downgraded payload apk",
+ DeviceRuntimeException.class,
+ () -> ensureMicrodroidBootsSuccessfully(INSTANCE_ID_FILE, INSTANCE_IMG));
+ }
+
+ private void ensureMicrodroidBootsSuccessfully(String instanceIdPath, String instanceImgPath)
+ throws DeviceNotAvailableException {
+ final String configPath = "assets/vm_config.json";
+ ITestDevice microdroid = null;
+ int timeout = 30000; // 30 seconds
+ try {
+ microdroid =
+ MicrodroidBuilder.fromDevicePath(getPathForPackage(PACKAGE_NAME), configPath)
+ .debugLevel("full")
+ .memoryMib(minMemorySize())
+ .cpuTopology("match_host")
+ .protectedVm(mProtectedVm)
+ .instanceIdFile(instanceIdPath)
+ .instanceImgFile(instanceImgPath)
+ .setAdbConnectTimeoutMs(timeout)
+ .build(getAndroidDevice());
+ assertThat(microdroid.waitForBootComplete(timeout)).isTrue();
+ assertThat(microdroid.enableAdbRoot()).isTrue();
+ } finally {
+ if (microdroid != null) {
+ getAndroidDevice().shutdownMicrodroid(microdroid);
+ }
+ }
+ }
+
+ @Test
@CddTest(requirements = {"9.17/C-2-1", "9.17/C-2-2", "9.17/C-2-6"})
public void protectedVmRunsPvmfw() throws Exception {
// Arrange
@@ -427,7 +493,7 @@
// Assert
mMicrodroidDevice.waitForBootComplete(BOOT_COMPLETE_TIMEOUT);
- String consoleLog = getDevice().pullFileContents(CONSOLE_PATH);
+ String consoleLog = getDevice().pullFileContents(TRADEFED_CONSOLE_PATH);
assertWithMessage("Failed to verify that pvmfw started")
.that(consoleLog)
.contains("pVM firmware");
@@ -1106,7 +1172,7 @@
prepareVirtualizationTestSetup(getDevice());
- getDevice().installPackage(findTestFile(APK_NAME), /* reinstall */ false);
+ getDevice().installPackage(findTestFile(APK_NAME), /* reinstall= */ false);
// Skip test if given device doesn't support protected or non-protected VM.
assumeTrue(
@@ -1159,6 +1225,12 @@
&& device.doesFileExist("/sys/bus/platform/drivers/vfio-platform"));
}
+ private void assumeUpdatableVmSupported() throws DeviceNotAvailableException {
+ assumeTrue(
+ "This test is only applicable if if Updatable VMs are supported",
+ isUpdatableVmSupported());
+ }
+
private TestDevice getAndroidDevice() {
TestDevice androidDevice = (TestDevice) getDevice();
assertThat(androidDevice).isNotNull();
diff --git a/tests/pvmfw/java/com/android/pvmfw/test/CustomPvmfwHostTestCaseBase.java b/tests/pvmfw/java/com/android/pvmfw/test/CustomPvmfwHostTestCaseBase.java
index 541f5ec..3116cc5 100644
--- a/tests/pvmfw/java/com/android/pvmfw/test/CustomPvmfwHostTestCaseBase.java
+++ b/tests/pvmfw/java/com/android/pvmfw/test/CustomPvmfwHostTestCaseBase.java
@@ -19,7 +19,6 @@
import static com.android.tradefed.device.TestDevice.MicrodroidBuilder;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assume.assumeTrue;
@@ -27,12 +26,9 @@
import androidx.annotation.Nullable;
import com.android.microdroid.test.host.MicrodroidHostTestCaseBase;
-import com.android.microdroid.test.host.CommandRunner;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.device.TestDevice;
-import com.android.tradefed.util.CommandResult;
-import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.FileUtil;
import org.junit.After;
@@ -62,18 +58,12 @@
@NonNull public static final String CUSTOM_PVMFW_FILE_PREFIX = "pvmfw";
@NonNull public static final String CUSTOM_PVMFW_FILE_SUFFIX = ".bin";
- @NonNull public static final String CUSTOM_PVMFW_IMG_PATH = TEST_ROOT + PVMFW_FILE_NAME;
+
+ @NonNull
+ public static final String CUSTOM_PVMFW_IMG_PATH = TRADEFED_TEST_ROOT + PVMFW_FILE_NAME;
+
@NonNull public static final String CUSTOM_PVMFW_IMG_PATH_PROP = "hypervisor.pvmfw.path";
- @NonNull private static final String DUMPSYS = "dumpsys";
-
- @NonNull
- private static final String DUMPSYS_MISSING_SERVICE_MSG_PREFIX = "Can't find service: ";
-
- @NonNull
- private static final String SECRET_KEEPER_AIDL =
- "android.hardware.security.secretkeeper.ISecretkeeper/default";
-
@Nullable private File mPvmfwBinFileOnHost;
@Nullable private File mBccFileOnHost;
@Nullable private File mVmReferenceDtFile;
@@ -100,23 +90,7 @@
// This is prepared by AndroidTest.xml
mVmReferenceDtFile = mAndroidDevice.pullFile(VM_REFERENCE_DT_PATH);
- CommandRunner runner = new CommandRunner(mAndroidDevice);
- CommandResult result = runner.runForResult(DUMPSYS, SECRET_KEEPER_AIDL);
-
- // dumpsys prints 'Can't find service: ~' to stderr if secret keeper HAL is missing,
- // but it doesn't return any error code for it.
- // Read stderr to know whether secret keeper is supported, and stop test for any other case.
- assertWithMessage("Failed to run " + DUMPSYS + ", result=" + result)
- .that(result.getStatus() == CommandStatus.SUCCESS && result.getExitCode() == 0)
- .isTrue();
- if (result.getStderr() != null && !result.getStderr().trim().isEmpty()) {
- assertWithMessage(
- "Unexpected stderr from " + DUMPSYS + ", stderr=" + result.getStderr())
- .that(result.getStderr().trim().startsWith(DUMPSYS_MISSING_SERVICE_MSG_PREFIX))
- .isTrue();
- } else {
- mSecretKeeperSupported = true;
- }
+ mSecretKeeperSupported = isUpdatableVmSupported();
// Prepare for system properties for custom pvmfw.img.
// File will be prepared later in individual test and then pushed to device
diff --git a/tests/pvmfw/java/com/android/pvmfw/test/DebugPolicyHostTests.java b/tests/pvmfw/java/com/android/pvmfw/test/DebugPolicyHostTests.java
index 223f93f..2a6ab2d 100644
--- a/tests/pvmfw/java/com/android/pvmfw/test/DebugPolicyHostTests.java
+++ b/tests/pvmfw/java/com/android/pvmfw/test/DebugPolicyHostTests.java
@@ -50,7 +50,7 @@
@NonNull
private static final String CUSTOM_DEBUG_POLICY_PATH =
- TEST_ROOT + CUSTOM_DEBUG_POLICY_FILE_NAME;
+ TRADEFED_TEST_ROOT + CUSTOM_DEBUG_POLICY_FILE_NAME;
@NonNull
private static final String CUSTOM_DEBUG_POLICY_PATH_PROP =
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index 84bf098..471aea7 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -33,10 +33,10 @@
compile_multilib: "both",
}
-android_test {
- name: "MicrodroidTestApp",
- defaults: ["MicrodroidTestAppsDefaults"],
+java_defaults {
+ name: "MicrodroidVersionsTestAppDefaults",
srcs: ["src/java/**/*.java"],
+ defaults: ["MicrodroidTestAppsDefaults"],
static_libs: [
"MicrodroidDeviceTestHelper",
"VmAttestationTestUtil",
@@ -58,14 +58,27 @@
"libvm_attestation_test_payload",
],
min_sdk_version: "33",
+}
+
+android_test {
+ name: "MicrodroidTestApp",
+ defaults: ["MicrodroidVersionsTestAppDefaults"],
+ manifest: "AndroidManifestV5.xml",
// Defined in ../vmshareapp/Android.bp
data: [
+ ":MicrodroidTestAppUpdated",
":MicrodroidVmShareApp",
":test_microdroid_vendor_image",
":test_microdroid_vendor_image_unsigned",
],
}
+android_test_helper_app {
+ name: "MicrodroidTestAppUpdated",
+ defaults: ["MicrodroidVersionsTestAppDefaults"],
+ manifest: "AndroidManifestV6.xml",
+}
+
// Defaults shared between MicrodroidTestNativeLib and MicrodroidPayloadInOtherAppNativeLib shared
// libs. They are expected to share everything apart from the name, so that one app
// (MicrodroidTestApp) can start a payload defined in the another app (MicrodroidVmShareApp).
diff --git a/tests/testapk/AndroidManifest.xml b/tests/testapk/AndroidManifestV5.xml
similarity index 94%
copy from tests/testapk/AndroidManifest.xml
copy to tests/testapk/AndroidManifestV5.xml
index d6e6004..7d97680 100644
--- a/tests/testapk/AndroidManifest.xml
+++ b/tests/testapk/AndroidManifestV5.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.microdroid.test">
+ package="com.android.microdroid.test"
+ android:versionCode="5">
<uses-permission android:name="android.permission.MANAGE_VIRTUAL_MACHINE" />
<uses-permission android:name="android.permission.USE_CUSTOM_VIRTUAL_MACHINE" />
<uses-sdk android:minSdkVersion="33" android:targetSdkVersion="33" />
diff --git a/tests/testapk/AndroidManifest.xml b/tests/testapk/AndroidManifestV6.xml
similarity index 94%
rename from tests/testapk/AndroidManifest.xml
rename to tests/testapk/AndroidManifestV6.xml
index d6e6004..19d5674 100644
--- a/tests/testapk/AndroidManifest.xml
+++ b/tests/testapk/AndroidManifestV6.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.microdroid.test">
+ package="com.android.microdroid.test"
+ android:versionCode="6">
<uses-permission android:name="android.permission.MANAGE_VIRTUAL_MACHINE" />
<uses-permission android:name="android.permission.USE_CUSTOM_VIRTUAL_MACHINE" />
<uses-sdk android:minSdkVersion="33" android:targetSdkVersion="33" />
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 1195cd3..8f4df63 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -240,7 +240,7 @@
runVmAttestationService(TAG, vm, challenge, VM_ATTESTATION_MESSAGE.getBytes());
// Assert.
- assertThat(signingResult.status).isEqualTo(AttestationStatus.ATTESTATION_ERROR_UNSUPPORTED);
+ assertThat(signingResult.status).isEqualTo(AttestationStatus.ERROR_UNSUPPORTED);
}
@Test
@@ -267,7 +267,7 @@
runVmAttestationService(
TAG, vm, invalidChallenge, VM_ATTESTATION_MESSAGE.getBytes());
assertThat(signingResultInvalidChallenge.status)
- .isEqualTo(AttestationStatus.ATTESTATION_ERROR_INVALID_CHALLENGE);
+ .isEqualTo(AttestationStatus.ERROR_INVALID_CHALLENGE);
// Check with a valid challenge.
byte[] challenge = new byte[32];
@@ -277,10 +277,8 @@
assertWithMessage(
"VM attestation should either succeed or fail when the network is unstable")
.that(signingResult.status)
- .isAnyOf(
- AttestationStatus.ATTESTATION_OK,
- AttestationStatus.ATTESTATION_ERROR_ATTESTATION_FAILED);
- if (signingResult.status == AttestationStatus.ATTESTATION_OK) {
+ .isAnyOf(AttestationStatus.OK, AttestationStatus.ERROR_ATTESTATION_FAILED);
+ if (signingResult.status == AttestationStatus.OK) {
X509Certificate[] certs =
X509Utils.validateAndParseX509CertChain(signingResult.certificateChain);
X509Utils.verifyAvfRelatedCerts(certs, challenge, TEST_APP_PACKAGE_NAME);
diff --git a/vmbase/Android.bp b/vmbase/Android.bp
index e797aa4..07e1b4c 100644
--- a/vmbase/Android.bp
+++ b/vmbase/Android.bp
@@ -57,8 +57,6 @@
hwaddress: false,
},
native_coverage: false,
- // Use --lto-O0 to reduce binary size.
- lto_O0: true,
}
// Used by cc_binary when producing the ELF of a vmbase-based binary.
diff --git a/zipfuse/src/main.rs b/zipfuse/src/main.rs
index e8be42c..ef31a0c 100644
--- a/zipfuse/src/main.rs
+++ b/zipfuse/src/main.rs
@@ -320,6 +320,7 @@
}
}
+ #[allow(clippy::unused_io_amount)]
fn read<W: io::Write + ZeroCopyWriter>(
&self,
_ctx: Context,