Merge "Uninstall the test app in shutdown"
diff --git a/compos/verify/verify.rs b/compos/verify/verify.rs
index 4dc9954..7b77c18 100644
--- a/compos/verify/verify.rs
+++ b/compos/verify/verify.rs
@@ -22,7 +22,8 @@
 use compos_aidl_interface::binder::ProcessState;
 use compos_common::compos_client::{VmInstance, VmParameters};
 use compos_common::odrefresh::{
-    CURRENT_ARTIFACTS_SUBDIR, ODREFRESH_OUTPUT_ROOT_DIR, TEST_ARTIFACTS_SUBDIR,
+    CURRENT_ARTIFACTS_SUBDIR, ODREFRESH_OUTPUT_ROOT_DIR, PENDING_ARTIFACTS_SUBDIR,
+    TEST_ARTIFACTS_SUBDIR,
 };
 use compos_common::{
     COMPOS_DATA_ROOT, CURRENT_INSTANCE_DIR, IDSIG_FILE, IDSIG_MANIFEST_APK_FILE,
@@ -62,7 +63,7 @@
                 .long("instance")
                 .takes_value(true)
                 .required(true)
-                .possible_values(&["current", "test"]),
+                .possible_values(&["current", "pending", "test"]),
         )
         .arg(clap::Arg::with_name("debug").long("debug"))
         .get_matches();
@@ -70,6 +71,7 @@
     let debug_mode = matches.is_present("debug");
     let (instance_dir, artifacts_dir) = match matches.value_of("instance").unwrap() {
         "current" => (CURRENT_INSTANCE_DIR, CURRENT_ARTIFACTS_SUBDIR),
+        "pending" => (CURRENT_INSTANCE_DIR, PENDING_ARTIFACTS_SUBDIR),
         "test" => (TEST_INSTANCE_DIR, TEST_ARTIFACTS_SUBDIR),
         _ => unreachable!("Unexpected instance name"),
     };
diff --git a/microdroid/Android.bp b/microdroid/Android.bp
index 3ae4b1a..0ca7036 100644
--- a/microdroid/Android.bp
+++ b/microdroid/Android.bp
@@ -59,7 +59,6 @@
         "libstdc++",
         "logcat",
         "logd",
-        "run-as",
         "secilc",
 
         // "com.android.adbd" requires these,
diff --git a/microdroid/bootconfig.normal b/microdroid/bootconfig.normal
index 708d64b..ea83287 100644
--- a/microdroid/bootconfig.normal
+++ b/microdroid/bootconfig.normal
@@ -7,7 +7,8 @@
 # Console output is not redirect to the host-side.
 # TODO(b/219743539) This doesn't successfully disable the console
 kernel.printk.devkmsg=off
-kernel.console=null
+# TODO(b/219743539) Setting this to null makes everything slow
+kernel.console=hvc0
 
 # ADB is not enabled.
 androidboot.adb.enabled=0
diff --git a/microdroid/dice/service.rs b/microdroid/dice/service.rs
index 8cb5cc3..8199c7c 100644
--- a/microdroid/dice/service.rs
+++ b/microdroid/dice/service.rs
@@ -30,6 +30,7 @@
 use std::slice;
 use std::sync::Arc;
 
+const AVF_STRICT_BOOT: &str = "/sys/firmware/devicetree/base/chosen/avf,strict-boot";
 const DICE_HAL_SERVICE_NAME: &str = "android.hardware.security.dice.IDiceDevice/default";
 
 /// Artifacts that are mapped into the process address space from the driver.
@@ -135,16 +136,19 @@
 
 #[derive(Clone, Serialize, Deserialize)]
 enum DriverArtifactManager {
+    Invalid,
     Driver(PathBuf),
     Updated(RawArtifacts),
 }
 
 impl DriverArtifactManager {
     fn new(driver_path: &Path) -> Self {
-        // TODO(218793274): fail if driver is missing in protected mode
         if driver_path.exists() {
             log::info!("Using DICE values from driver");
             Self::Driver(driver_path.to_path_buf())
+        } else if Path::new(AVF_STRICT_BOOT).exists() {
+            log::error!("Strict boot requires DICE value from driver but none were found");
+            Self::Invalid
         } else {
             log::warn!("Using sample DICE values");
             let (cdi_attest, cdi_seal, bcc) = diced_sample_inputs::make_sample_bcc_and_cdis()
@@ -164,11 +168,15 @@
         F: FnOnce(&dyn DiceArtifacts) -> Result<T>,
     {
         match self {
+            Self::Invalid => bail!("No DICE artifacts available."),
             Self::Driver(driver_path) => f(&MappedDriverArtifacts::new(driver_path.as_path())?),
             Self::Updated(raw_artifacts) => f(raw_artifacts),
         }
     }
     fn update(self, new_artifacts: &impl DiceArtifacts) -> Result<Self> {
+        if let Self::Invalid = self {
+            bail!("Cannot update invalid DICE artifacts.");
+        }
         if let Self::Driver(driver_path) = self {
             // Writing to the device wipes the artifcates. The string is ignored
             // by the driver but included for documentation.
diff --git a/microdroid/init.rc b/microdroid/init.rc
index 5f0001f..2ccdc3b 100644
--- a/microdroid/init.rc
+++ b/microdroid/init.rc
@@ -83,6 +83,10 @@
 
     setprop ro.debuggable ${ro.boot.microdroid.debuggable:-0}
 
+on init && property:ro.boot.microdroid.debuggable=1
+    # Mount tracefs (with GID=AID_READTRACEFS)
+    mount tracefs tracefs /sys/kernel/tracing gid=3012
+
 on init && property:ro.boot.logd.enabled=1
     # Start logd before any other services run to ensure we capture all of their logs.
     start logd
@@ -144,6 +148,12 @@
     mkdir /data/misc/authfs 0700 root root
     start authfs_service
 
+on late-fs && property:ro.debuggable=1
+    # Ensure that tracefs has the correct permissions.
+    # This does not work correctly if it is called in post-fs.
+    chmod 0755 /sys/kernel/tracing
+    chmod 0755 /sys/kernel/debug/tracing
+
 on post-fs-data
     mark_post_data
 
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index b644285..9e159d2 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -61,6 +61,8 @@
 const DM_MOUNTED_APK_PATH: &str = "/dev/block/mapper/microdroid-apk";
 const APKDMVERITY_BIN: &str = "/system/bin/apkdmverity";
 const ZIPFUSE_BIN: &str = "/system/bin/zipfuse";
+const AVF_STRICT_BOOT: &str = "/sys/firmware/devicetree/base/chosen/avf,strict-boot";
+const AVF_NEW_INSTANCE: &str = "/sys/firmware/devicetree/base/chosen/avf,new-instance";
 
 /// The CID representing the host VM
 const VMADDR_CID_HOST: u32 = 2;
@@ -193,12 +195,35 @@
     Ok(())
 }
 
+fn is_strict_boot() -> bool {
+    Path::new(AVF_STRICT_BOOT).exists()
+}
+
+fn is_new_instance() -> bool {
+    Path::new(AVF_NEW_INSTANCE).exists()
+}
+
 fn try_run_payload(service: &Strong<dyn IVirtualMachineService>) -> Result<i32> {
     let metadata = load_metadata().context("Failed to load payload metadata")?;
 
     let mut instance = InstanceDisk::new().context("Failed to load instance.img")?;
     let saved_data = instance.read_microdroid_data().context("Failed to read identity data")?;
 
+    if is_strict_boot() {
+        // Provisioning must happen on the first boot and never again.
+        if is_new_instance() {
+            ensure!(
+                saved_data.is_none(),
+                MicrodroidError::InvalidConfig("Found instance data on first boot.".to_string())
+            );
+        } else {
+            ensure!(
+                saved_data.is_some(),
+                MicrodroidError::InvalidConfig("Instance data not found.".to_string())
+            );
+        };
+    }
+
     // Verify the payload before using it.
     let verified_data =
         verify_payload(&metadata, saved_data.as_ref()).context("Payload verification failed")?;
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 8df853d..36bea72 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -544,8 +544,7 @@
                 .isNotEqualTo("vsoc_x86_64");
 
         if (mProtectedVm) {
-            // TODO(b/218461230): uncomment this after u-boot update
-            // assertThatBootFailsAfterCompromisingPartition(U_BOOT_AVB_PARTITION_UUID);
+            assertThatBootFailsAfterCompromisingPartition(U_BOOT_AVB_PARTITION_UUID);
         } else {
             // non-protected VM shouldn't have u-boot avb data
             assertThatPartitionIsMissing(U_BOOT_AVB_PARTITION_UUID);
@@ -560,8 +559,7 @@
                 .isNotEqualTo("vsoc_x86_64");
 
         if (mProtectedVm) {
-            // TODO(b/218461230): uncomment this after u-boot update
-            // assertThatBootFailsAfterCompromisingPartition(U_BOOT_ENV_PARTITION_UUID);
+            assertThatBootFailsAfterCompromisingPartition(U_BOOT_ENV_PARTITION_UUID);
         } else {
             // non-protected VM shouldn't have u-boot env data
             assertThatPartitionIsMissing(U_BOOT_ENV_PARTITION_UUID);