Merge "Pass dt symbol argument for devices to crosvm" into main
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index e9cb0ec..a496d53 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -144,18 +144,9 @@
         Owned(format!("MICRODROID_UNKNOWN_RUNTIME_ERROR|{:?}", err))
     };
 
-    let death_reason_bytes = death_reason.as_bytes();
-    let mut sent_total = 0;
-    while sent_total < death_reason_bytes.len() {
+    for chunk in death_reason.as_bytes().chunks(16) {
         // TODO(b/220071963): Sometimes, sending more than 16 bytes at once makes MM hang.
-        let begin = sent_total;
-        let end = std::cmp::min(begin.saturating_add(16), death_reason_bytes.len());
-        OpenOptions::new()
-            .read(false)
-            .write(true)
-            .open(FAILURE_SERIAL_DEVICE)?
-            .write_all(&death_reason_bytes[begin..end])?;
-        sent_total = end;
+        OpenOptions::new().read(false).write(true).open(FAILURE_SERIAL_DEVICE)?.write_all(chunk)?;
     }
 
     Ok(())
diff --git a/tests/pvmfw/Android.bp b/tests/pvmfw/Android.bp
index 61667f3..474c62e 100644
--- a/tests/pvmfw/Android.bp
+++ b/tests/pvmfw/Android.bp
@@ -9,6 +9,20 @@
 }
 
 genrule {
+    name: "test_avf_debug_policy_with_ramdump",
+    defaults: ["test_avf_dts_to_dtb"],
+    srcs: ["assets/avf_debug_policy_with_ramdump.dts"],
+    out: ["avf_debug_policy_with_ramdump.dtbo"],
+}
+
+genrule {
+    name: "test_avf_debug_policy_without_ramdump",
+    defaults: ["test_avf_dts_to_dtb"],
+    srcs: ["assets/avf_debug_policy_without_ramdump.dts"],
+    out: ["avf_debug_policy_without_ramdump.dtbo"],
+}
+
+genrule {
     name: "test_avf_debug_policy_with_adb",
     defaults: ["test_avf_dts_to_dtb"],
     srcs: ["assets/avf_debug_policy_with_adb.dts"],
@@ -39,6 +53,8 @@
     data: [
         ":MicrodroidTestApp",
         ":pvmfw_test",
+        ":test_avf_debug_policy_with_ramdump",
+        ":test_avf_debug_policy_without_ramdump",
         ":test_avf_debug_policy_with_adb",
         ":test_avf_debug_policy_without_adb",
         "assets/bcc.dat",
diff --git a/tests/pvmfw/assets/avf_debug_policy_with_ramdump.dts b/tests/pvmfw/assets/avf_debug_policy_with_ramdump.dts
new file mode 100644
index 0000000..139d28e
--- /dev/null
+++ b/tests/pvmfw/assets/avf_debug_policy_with_ramdump.dts
@@ -0,0 +1,22 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+    fragment@avf {
+        target-path = "/";
+
+        __overlay__ {
+            avf {
+                guest {
+                    common {
+                        ramdump = <1>;
+                    };
+                    microdroid {
+                        adb = <1>; // adb is required to check VM's bootargs.
+                    };
+                };
+            };
+        };
+    };
+};
+
diff --git a/tests/pvmfw/assets/avf_debug_policy_without_ramdump.dts b/tests/pvmfw/assets/avf_debug_policy_without_ramdump.dts
new file mode 100644
index 0000000..8e0e44c
--- /dev/null
+++ b/tests/pvmfw/assets/avf_debug_policy_without_ramdump.dts
@@ -0,0 +1,22 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+    fragment@avf {
+        target-path = "/";
+
+        __overlay__ {
+            avf {
+                guest {
+                    common {
+                        ramdump = <0>;
+                    };
+                    microdroid {
+                        adb = <1>; // adb is required to check VM's bootargs.
+                    };
+                };
+            };
+        };
+    };
+};
+
diff --git a/tests/pvmfw/java/com/android/pvmfw/test/DebugPolicyHostTests.java b/tests/pvmfw/java/com/android/pvmfw/test/DebugPolicyHostTests.java
index 410e6e0..7d0faa4 100644
--- a/tests/pvmfw/java/com/android/pvmfw/test/DebugPolicyHostTests.java
+++ b/tests/pvmfw/java/com/android/pvmfw/test/DebugPolicyHostTests.java
@@ -192,6 +192,43 @@
         launchProtectedVmAndWaitForBootCompleted(MICRODROID_DEBUG_FULL);
     }
 
+    @Test
+    public void testRamdumpInDebugPolicy_withDebugLevelNone_hasRamdumpArgs() throws Exception {
+        prepareCustomDebugPolicy("avf_debug_policy_with_ramdump.dtbo");
+        mMicrodroidDevice = launchProtectedVmAndWaitForBootCompleted(MICRODROID_DEBUG_NONE);
+
+        assertThat(readMicrodroidFileAsString(MICRODROID_CMDLINE_PATH)).contains("crashkernel=");
+        assertThat(readMicrodroidFileAsString(MICRODROID_DT_BOOTARGS_PATH))
+                .contains("crashkernel=");
+        assertThat(readMicrodroidFileAsHexString(MICRODROID_DT_RAMDUMP_PATH))
+                .isEqualTo(HEX_STRING_ONE);
+    }
+
+    @Test
+    public void testNoRamdumpInDebugPolicy_withDebugLevelNone_noRamdumpArgs() throws Exception {
+        prepareCustomDebugPolicy("avf_debug_policy_without_ramdump.dtbo");
+        mMicrodroidDevice = launchProtectedVmAndWaitForBootCompleted(MICRODROID_DEBUG_NONE);
+
+        assertThat(readMicrodroidFileAsString(MICRODROID_CMDLINE_PATH))
+                .doesNotContain("crashkernel=");
+        assertThat(readMicrodroidFileAsString(MICRODROID_DT_BOOTARGS_PATH))
+                .doesNotContain("crashkernel=");
+        assertThat(readMicrodroidFileAsHexString(MICRODROID_DT_RAMDUMP_PATH))
+                .isEqualTo(HEX_STRING_ZERO);
+    }
+
+    @Test
+    public void testNoRamdumpInDebugPolicy_withDebugLevelFull_hasRamdumpArgs() throws Exception {
+        prepareCustomDebugPolicy("avf_debug_policy_without_ramdump.dtbo");
+        mMicrodroidDevice = launchProtectedVmAndWaitForBootCompleted(MICRODROID_DEBUG_FULL);
+
+        assertThat(readMicrodroidFileAsString(MICRODROID_CMDLINE_PATH)).contains("crashkernel=");
+        assertThat(readMicrodroidFileAsString(MICRODROID_DT_BOOTARGS_PATH))
+                .contains("crashkernel=");
+        assertThat(readMicrodroidFileAsHexString(MICRODROID_DT_RAMDUMP_PATH))
+                .isEqualTo(HEX_STRING_ZERO);
+    }
+
     private boolean isDebugPolicyEnabled(@NonNull String dtPropertyPath)
             throws DeviceNotAvailableException {
         CommandRunner runner = new CommandRunner(mAndroidDevice);
diff --git a/virtualizationmanager/Android.bp b/virtualizationmanager/Android.bp
index c660414..12d8724 100644
--- a/virtualizationmanager/Android.bp
+++ b/virtualizationmanager/Android.bp
@@ -82,6 +82,8 @@
         "libtempfile",
     ],
     data: [
+        ":test_avf_debug_policy_with_ramdump",
+        ":test_avf_debug_policy_without_ramdump",
         ":test_avf_debug_policy_with_adb",
         ":test_avf_debug_policy_without_adb",
     ],
diff --git a/virtualizationmanager/src/crosvm.rs b/virtualizationmanager/src/crosvm.rs
index d14e2df..b053d99 100644
--- a/virtualizationmanager/src/crosvm.rs
+++ b/virtualizationmanager/src/crosvm.rs
@@ -649,10 +649,10 @@
 }
 
 fn death_reason(result: &Result<ExitStatus, io::Error>, mut failure_reason: &str) -> DeathReason {
-    if let Some(position) = failure_reason.find('|') {
+    if let Some((reason, info)) = failure_reason.split_once('|') {
         // Separator indicates extra context information is present after the failure name.
-        error!("Failure info: {}", &failure_reason[(position + 1)..]);
-        failure_reason = &failure_reason[..position];
+        error!("Failure info: {info}");
+        failure_reason = reason;
     }
     if let Ok(status) = result {
         match failure_reason {
diff --git a/virtualizationmanager/src/debug_config.rs b/virtualizationmanager/src/debug_config.rs
index 9b13475..5d22f59 100644
--- a/virtualizationmanager/src/debug_config.rs
+++ b/virtualizationmanager/src/debug_config.rs
@@ -239,6 +239,38 @@
     }
 
     #[test]
+    fn test_read_avf_debug_policy_with_ramdump() -> Result<()> {
+        let debug_config = DebugConfig::from_custom_debug_overlay_policy(
+            DebugLevel::FULL,
+            "avf_debug_policy_with_ramdump.dtbo".as_ref(),
+        )
+        .unwrap();
+
+        assert_eq!(DebugLevel::FULL, debug_config.debug_level);
+        assert!(!debug_config.debug_policy_log);
+        assert!(debug_config.debug_policy_ramdump);
+        assert!(debug_config.debug_policy_adb);
+
+        Ok(())
+    }
+
+    #[test]
+    fn test_read_avf_debug_policy_without_ramdump() -> Result<()> {
+        let debug_config = DebugConfig::from_custom_debug_overlay_policy(
+            DebugLevel::FULL,
+            "avf_debug_policy_without_ramdump.dtbo".as_ref(),
+        )
+        .unwrap();
+
+        assert_eq!(DebugLevel::FULL, debug_config.debug_level);
+        assert!(!debug_config.debug_policy_log);
+        assert!(!debug_config.debug_policy_ramdump);
+        assert!(debug_config.debug_policy_adb);
+
+        Ok(())
+    }
+
+    #[test]
     fn test_read_avf_debug_policy_with_adb() -> Result<()> {
         let debug_config = DebugConfig::from_custom_debug_overlay_policy(
             DebugLevel::FULL,
diff --git a/virtualizationservice/src/remote_provisioning.rs b/virtualizationservice/src/remote_provisioning.rs
index 06f8ad4..1c8d1e6 100644
--- a/virtualizationservice/src/remote_provisioning.rs
+++ b/virtualizationservice/src/remote_provisioning.rs
@@ -94,6 +94,16 @@
         keysToSign: &[MacedPublicKey],
         challenge: &[u8],
     ) -> BinderResult<Vec<u8>> {
+        const MAX_CHALLENGE_SIZE: usize = 64;
+        if challenge.len() > MAX_CHALLENGE_SIZE {
+            let message = format!(
+                "Challenge is too big. Actual: {:?}. Maximum: {:?}.",
+                challenge.len(),
+                MAX_CHALLENGE_SIZE
+            );
+            return Err(Status::new_service_specific_error_str(STATUS_FAILED, Some(message)))
+                .with_log();
+        }
         // TODO(b/299259624): Validate the MAC of the keys to certify.
         rkpvm::generate_certificate_request(keysToSign, challenge)
             .context("Failed to generate certificate request")