pvmfw: Support com.android.virt.page_size
Replace the assumption that guests run with 4KiB page tables by adding
support for a new VBMeta descriptor property describing the size in use.
When absent, default to the previous assumption of 4KiB.
Set the property for the Micrdroid kernels with 16KiB PAGE_SIZE.
Add test coverage & document this in the README.
Bug: 339779843
Bug: 339782511
Test: atest libpvmfw_avb.integration_test
Change-Id: Ib3c2b87fd507046578cc95d892d01fa9b04bc5c7
diff --git a/guest/pvmfw/avb/src/verify.rs b/guest/pvmfw/avb/src/verify.rs
index 2a7eed2..8810696 100644
--- a/guest/pvmfw/avb/src/verify.rs
+++ b/guest/pvmfw/avb/src/verify.rs
@@ -22,6 +22,7 @@
Descriptor, DescriptorError, DescriptorResult, HashDescriptor, PartitionData, SlotVerifyError,
SlotVerifyNoDataResult, VbmetaData,
};
+use core::str;
// We use this for the rollback_index field if SlotVerifyData has empty rollback_indexes
const DEFAULT_ROLLBACK_INDEX: u64 = 0;
@@ -220,6 +221,23 @@
Ok(digest)
}
+/// Returns the indicated payload page size, if present.
+fn read_page_size(vbmeta_data: &VbmetaData) -> Result<Option<usize>, PvmfwVerifyError> {
+ let Some(property) = vbmeta_data.get_property_value("com.android.virt.page_size") else {
+ return Ok(None);
+ };
+ let size = str::from_utf8(property)
+ .or(Err(PvmfwVerifyError::InvalidPageSize))?
+ .parse::<usize>()
+ .or(Err(PvmfwVerifyError::InvalidPageSize))?
+ .checked_mul(1024)
+ // TODO(stable(unsigned_is_multiple_of)): use .is_multiple_of()
+ .filter(|sz| sz % (4 << 10) == 0 && *sz != 0)
+ .ok_or(PvmfwVerifyError::InvalidPageSize)?;
+
+ Ok(Some(size))
+}
+
/// Verifies the given initrd partition, and checks that the resulting contents looks like expected.
fn verify_initrd(
ops: &mut Ops,
@@ -256,7 +274,7 @@
let descriptors = vbmeta_image.descriptors()?;
let hash_descriptors = HashDescriptors::get(&descriptors)?;
let capabilities = Capability::get_capabilities(vbmeta_image)?;
- let page_size = None; // TODO(ptosi): Read from payload.
+ let page_size = read_page_size(vbmeta_image)?;
if initrd.is_none() {
hash_descriptors.verify_no_initrd()?;