Merge "Cache package name not APK path"
diff --git a/pvmfw/avb/src/ops.rs b/pvmfw/avb/src/ops.rs
index 903fecb..e7f0ac7 100644
--- a/pvmfw/avb/src/ops.rs
+++ b/pvmfw/avb/src/ops.rs
@@ -21,7 +21,7 @@
 use crate::utils::{self, as_ref, is_not_null, to_nonnull, write};
 use avb_bindgen::{
     avb_slot_verify, avb_slot_verify_data_free, AvbHashtreeErrorMode, AvbIOResult, AvbOps,
-    AvbSlotVerifyData, AvbSlotVerifyFlags, AvbVBMetaData,
+    AvbPartitionData, AvbSlotVerifyData, AvbSlotVerifyFlags, AvbVBMetaData,
 };
 use core::{
     ffi::{c_char, c_void, CStr},
@@ -229,15 +229,13 @@
 extern "C" fn read_rollback_index(
     _ops: *mut AvbOps,
     _rollback_index_location: usize,
-    _out_rollback_index: *mut u64,
+    out_rollback_index: *mut u64,
 ) -> AvbIOResult {
-    // TODO(b/256148034): Write -1 to out_rollback_index
-    // so that we won't compare the current rollback index with uninitialized number
-    // in avb_slot_verify.
-
-    // Rollback protection is not yet implemented, but
-    // this method is required by `avb_slot_verify()`.
-    AvbIOResult::AVB_IO_RESULT_OK
+    // Rollback protection is not yet implemented, but this method is required by
+    // `avb_slot_verify()`.
+    // We set `out_rollback_index` to 0 to ensure that the default rollback index (0)
+    // is never smaller than it, thus the rollback index check will pass.
+    to_avb_io_result(write(out_rollback_index, 0))
 }
 
 extern "C" fn get_unique_guid_for_partition(
@@ -327,4 +325,15 @@
             unsafe { slice::from_raw_parts(data.vbmeta_images, data.num_vbmeta_images) };
         Ok(vbmeta_images)
     }
+
+    pub(crate) fn loaded_partitions(&self) -> Result<&[AvbPartitionData], AvbSlotVerifyError> {
+        let data = self.as_ref();
+        is_not_null(data.loaded_partitions).map_err(|_| AvbSlotVerifyError::Io)?;
+        // SAFETY: It is safe as the raw pointer `data.loaded_partitions` is a nonnull pointer and
+        // is guaranteed by libavb to point to a valid `AvbPartitionData` array as part of the
+        // `AvbSlotVerifyData` struct.
+        let loaded_partitions =
+            unsafe { slice::from_raw_parts(data.loaded_partitions, data.num_loaded_partitions) };
+        Ok(loaded_partitions)
+    }
 }
diff --git a/pvmfw/avb/src/verify.rs b/pvmfw/avb/src/verify.rs
index d6a0cb2..a062061 100644
--- a/pvmfw/avb/src/verify.rs
+++ b/pvmfw/avb/src/verify.rs
@@ -20,7 +20,7 @@
 use crate::utils::{is_not_null, to_usize, usize_checked_add, write};
 use avb_bindgen::{
     avb_descriptor_foreach, avb_hash_descriptor_validate_and_byteswap, AvbDescriptor,
-    AvbHashDescriptor, AvbVBMetaData,
+    AvbHashDescriptor, AvbPartitionData, AvbVBMetaData,
 };
 use core::{
     ffi::{c_char, c_void},
@@ -135,6 +135,16 @@
     }
 }
 
+fn verify_only_one_vbmeta_exists(
+    vbmeta_images: &[AvbVBMetaData],
+) -> Result<(), AvbSlotVerifyError> {
+    if vbmeta_images.len() == 1 {
+        Ok(())
+    } else {
+        Err(AvbSlotVerifyError::InvalidMetadata)
+    }
+}
+
 fn verify_vbmeta_is_from_kernel_partition(
     vbmeta_image: &AvbVBMetaData,
 ) -> Result<(), AvbSlotVerifyError> {
@@ -144,6 +154,29 @@
     }
 }
 
+fn verify_loaded_partition_has_expected_length(
+    loaded_partitions: &[AvbPartitionData],
+    partition_name: PartitionName,
+    expected_len: usize,
+) -> Result<(), AvbSlotVerifyError> {
+    if loaded_partitions.len() != 1 {
+        // Only one partition should be loaded in each verify result.
+        return Err(AvbSlotVerifyError::Io);
+    }
+    let loaded_partition = loaded_partitions[0];
+    if !PartitionName::try_from(loaded_partition.partition_name as *const c_char)
+        .map_or(false, |p| p == partition_name)
+    {
+        // Only the requested partition should be loaded.
+        return Err(AvbSlotVerifyError::Io);
+    }
+    if loaded_partition.data_size == expected_len {
+        Ok(())
+    } else {
+        Err(AvbSlotVerifyError::Verification)
+    }
+}
+
 /// Verifies the payload (signed kernel + initrd) against the trusted public key.
 pub fn verify_payload(
     kernel: &[u8],
@@ -153,13 +186,12 @@
     let mut payload = Payload::new(kernel, initrd, trusted_public_key);
     let mut ops = Ops::from(&mut payload);
     let kernel_verify_result = ops.verify_partition(PartitionName::Kernel.as_cstr())?;
+
     let vbmeta_images = kernel_verify_result.vbmeta_images()?;
-    if vbmeta_images.len() != 1 {
-        // There can only be one VBMeta.
-        return Err(AvbSlotVerifyError::InvalidMetadata);
-    }
+    verify_only_one_vbmeta_exists(vbmeta_images)?;
     let vbmeta_image = vbmeta_images[0];
     verify_vbmeta_is_from_kernel_partition(&vbmeta_image)?;
+
     if initrd.is_none() {
         verify_vbmeta_has_no_initrd_descriptor(&vbmeta_image)?;
         return Ok(DebugLevel::None);
@@ -167,12 +199,20 @@
     // TODO(b/256148034): Check the vbmeta doesn't have hash descriptors other than
     // boot, initrd_normal, initrd_debug.
 
-    let debug_level = if ops.verify_partition(PartitionName::InitrdNormal.as_cstr()).is_ok() {
-        DebugLevel::None
-    } else if ops.verify_partition(PartitionName::InitrdDebug.as_cstr()).is_ok() {
-        DebugLevel::Full
-    } else {
-        return Err(AvbSlotVerifyError::Verification);
-    };
+    let initrd = initrd.unwrap();
+    let (debug_level, initrd_verify_result, initrd_partition_name) =
+        if let Ok(result) = ops.verify_partition(PartitionName::InitrdNormal.as_cstr()) {
+            (DebugLevel::None, result, PartitionName::InitrdNormal)
+        } else if let Ok(result) = ops.verify_partition(PartitionName::InitrdDebug.as_cstr()) {
+            (DebugLevel::Full, result, PartitionName::InitrdDebug)
+        } else {
+            return Err(AvbSlotVerifyError::Verification);
+        };
+    let loaded_partitions = initrd_verify_result.loaded_partitions()?;
+    verify_loaded_partition_has_expected_length(
+        loaded_partitions,
+        initrd_partition_name,
+        initrd.len(),
+    )?;
     Ok(debug_level)
 }
diff --git a/pvmfw/avb/tests/api_test.rs b/pvmfw/avb/tests/api_test.rs
index 41ead59..0572789 100644
--- a/pvmfw/avb/tests/api_test.rs
+++ b/pvmfw/avb/tests/api_test.rs
@@ -202,6 +202,19 @@
 }
 
 #[test]
+fn extended_initrd_fails_verification() -> Result<()> {
+    let mut initrd = load_latest_initrd_normal()?;
+    initrd.extend(b"androidboot.vbmeta.digest=1111");
+
+    assert_payload_verification_with_initrd_eq(
+        &load_latest_signed_kernel()?,
+        &initrd,
+        &load_trusted_public_key()?,
+        Err(AvbSlotVerifyError::Verification),
+    )
+}
+
+#[test]
 fn tampered_vbmeta_fails_verification() -> Result<()> {
     let mut kernel = load_latest_signed_kernel()?;
     let footer = extract_avb_footer(&kernel)?;