Merge "Validate setOs and --gki when creating a VM" into main
diff --git a/microdroid/README.md b/microdroid/README.md
index dd1505f..c82ef0b 100644
--- a/microdroid/README.md
+++ b/microdroid/README.md
@@ -138,6 +138,53 @@
 If you are looking for an example usage of the APIs, you may refer to the [demo
 app](https://android.googlesource.com/platform/packages/modules/Virtualization/+/refs/heads/master/demo/).
 
+
+## Running Microdroid with vendor image
+
+With using `vm` tool, execute the following commands to launch a VM with vendor
+partition.
+
+```sh
+adb shell /apex/com.android.virt/bin/vm run-microdroid \
+--vendor $VENDOR_IMAGE
+```
+
+### Verification of vendor image
+
+Since vendor image of Microdroid is not part of `com.android.virt` APEX, the
+verification process of vendor partition is different from others.
+
+Vendor image uses its hashtree digest for the verifying its data, generated
+by `add_hashtree_footer` in `avbtool`. The value could be seen with following
+command:
+
+```sh
+avbtool info_image --image $VENDOR_IMAGE
+```
+
+Fixed path in VM for vendor hashtree digest is written in [fstab.microdroid].
+During first stage init of VM, [dm-verity] is set up based on vendor hashtree
+digest by reading [fstab.microdroid].
+
+For non-pVM, virtualizationmanager creates [DTBO] containing vendor hashtree
+digest, and passes to the VM via crosvm option. The vendor hashtree digest is
+obtained by virtualizationmanager from the host Android DT under
+`/avf/reference/`, which may be populated by the [bootloader].
+
+For pVM, VM reference DT included in [pvmfw config data] is additionally used
+for validating vendor hashtree digest. [Bootloader][bootloader] should append
+vendor hashtree digest into VM reference DT based on [fstab.microdroid]. Vendor
+hashtree digest could be appended as property into descriptors in host Android's
+vendor image by [Makefile] when Microdroid vendor image module is defined, so
+that a [bootloader] can extract the value and populate into VM reference DT.
+
+[fstab.microdroid]: fstab.microdroid
+[dm-verity]: https://source.android.com/docs/security/features/verifiedboot/dm-verity
+[DTBO]: https://android.googlesource.com/platform/external/dtc/+/refs/heads/main/Documentation/dt-object-internal.txt
+[pvmfw config data]: ../pvmfw/README.md#configuration-data-format
+[bootloader]: https://source.android.com/docs/core/architecture/bootloader
+[Makefile]: https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile
+
 ## Debugging Microdroid
 
 Refer to [Debugging protected VMs](../docs/debug/README.md).
diff --git a/microdroid/kernel/README.md b/microdroid/kernel/README.md
index 78ac81b..92b7cfe 100644
--- a/microdroid/kernel/README.md
+++ b/microdroid/kernel/README.md
@@ -19,13 +19,13 @@
 For ARM64
 ```bash
 tools/bazel clean
-tools/bazel run --config=fast --lto=thin //common-modules/virtual-device:microdroid_aarch64_dist -- --dist_dir=out/dist
+tooln/bazel run --config=fast //common:kernel_aarch64_microdroid_dist -- --dist_dir=out/dist
 ```
 
 For x86\_64,
 ```bash
 tools/bazel clean
-tools/bazel run --config=fast --lto=thin //common-modules/virtual-device:microdroid_x86_64_dist -- --dist_dir=out/dist
+tools/bazel run --config=fast //common:kernel_x86_64_microdroid_dist -- --dist_dir=out/dist
 ```
 
 Note that
@@ -39,12 +39,12 @@
 
 For ARM64
 ```bash
-tools/bazel run //common-modules/virtual-device:microdroid_aarch64_config -- menuconfig
+tools/bazel run //common:kernel_aarch64_microdroid_config -- menuconfig
 ```
 
 For x86\_64
 ```bash
-tools/bazel run //common-modules/virtual-device:microdroid_x86_64_config -- menuconfig
+tools/bazel run //common:kernel_x86_64_microdroid_config -- menuconfig
 ```
 
 ## How to update Microdroid kernel prebuilts
diff --git a/pvmfw/README.md b/pvmfw/README.md
index 124ef89..795bb05 100644
--- a/pvmfw/README.md
+++ b/pvmfw/README.md
@@ -141,7 +141,11 @@
 +-------------------------------+
 |           [Entry 2]           | <-- Entry 2 is present since version 1.1
 |  offset = (THIRD - HEAD)      |
-|  size = (THIRD_END - SECOND)  |
+|  size = (THIRD_END - THIRD)   |
++-------------------------------+
+|           [Entry 3]           | <-- Entry 3 is present since version 1.2
+|  offset = (FOURTH - HEAD)     |
+|  size = (FOURTH_END - FOURTH) |
 +-------------------------------+
 |              ...              |
 +-------------------------------+
@@ -149,17 +153,21 @@
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 | (Padding to 8-byte alignment) |
 +===============================+ <-- FIRST
-|        {First blob: BCC}      |
+|       {First blob: BCC}       |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ <-- FIRST_END
 | (Padding to 8-byte alignment) |
 +===============================+ <-- SECOND
-|        {Second blob: DP}      |
+|       {Second blob: DP}       |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ <-- SECOND_END
 | (Padding to 8-byte alignment) |
 +===============================+ <-- THIRD
-|        {Third blob: VM DTBO}  |
+|     {Third blob: VM DTBO}     |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ <-- THIRD_END
 | (Padding to 8-byte alignment) |
++===============================+ <-- FOURTH
+| {Fourth blob: VM reference DT}|
++~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ <-- FOURTH_END
+| (Padding to 8-byte alignment) |
 +===============================+
 |              ...              |
 +===============================+ <-- TAIL
@@ -185,14 +193,38 @@
 - entry 1 may point to a [DTBO] to be applied to the pVM device tree. See
   [debug policy][debug_policy] for an example.
 
-In version 1.1, new blob is added.
+In version 1.1, a third blob is added.
 
 - entry 2 may point to a [DTBO] that describes VM DTBO for device assignment.
   pvmfw will provision assigned devices with the VM DTBO.
 
+In version 1.2, a fourth blob is added.
+
+- entry 3 if present contains the VM reference DT. This defines properties that
+  may be included in the device tree passed to a protected VM. pvmfw validates
+  that if any of these properties is included in the VM's device tree, the
+  property value exactly matches what is in the VM reference DT.
+
+  The bootloader should ensure that the same properties, with the same values,
+  are added under the "/avf/reference" node in the host Android device tree.
+
+  This provides a mechanism to allow configuration information to be securely
+  passed to the VM via the host. pvmfw does not interpret the content of VM
+  reference DT, nor does it apply it to the VM's device tree, it just ensures
+  that if matching properties are present in the VM device tree they contain the
+  correct values.
+
+  One use case for this mechanism is passing the [public key of the
+  Secretkeeper][secretkeeper_key] HAL implementation to each VM.
+
+<!--
+  TODO(b/319192461): Attach link explaining about Microdroid vendor partition
+-->
+
 [header]: src/config.rs
 [DTBO]: https://android.googlesource.com/platform/external/dtc/+/refs/heads/main/Documentation/dt-object-internal.txt
 [debug_policy]: ../docs/debug/README.md#debug-policy
+[secretkeeper_key]: https://android.googlesource.com/platform/system/secretkeeper/+/refs/heads/main/README.md#secretkeeper-public-key
 
 #### Virtual Platform Boot Certificate Chain Handover
 
diff --git a/pvmfw/src/config.rs b/pvmfw/src/config.rs
index 7b548ce..5a3d138 100644
--- a/pvmfw/src/config.rs
+++ b/pvmfw/src/config.rs
@@ -141,7 +141,7 @@
     pub bcc: &'a mut [u8],
     pub debug_policy: Option<&'a [u8]>,
     pub vm_dtbo: Option<&'a mut [u8]>,
-    pub vm_base_dtbo: Option<&'a [u8]>,
+    pub vm_ref_dt: Option<&'a [u8]>,
 }
 
 #[repr(packed)]
@@ -290,15 +290,15 @@
                 entries[i] = Some(chunk);
             }
         }
-        let [bcc, debug_policy, vm_dtbo, vm_base_dtbo] = entries;
+        let [bcc, debug_policy, vm_dtbo, vm_ref_dt] = entries;
 
         // The platform BCC has always been required.
         let bcc = bcc.unwrap();
 
         // We have no reason to mutate so drop the `mut`.
         let debug_policy = debug_policy.map(|x| &*x);
-        let vm_base_dtbo = vm_base_dtbo.map(|x| &*x);
+        let vm_ref_dt = vm_ref_dt.map(|x| &*x);
 
-        Entries { bcc, debug_policy, vm_dtbo, vm_base_dtbo }
+        Entries { bcc, debug_policy, vm_dtbo, vm_ref_dt }
     }
 }
diff --git a/pvmfw/src/entry.rs b/pvmfw/src/entry.rs
index 8eca7a1..253604b 100644
--- a/pvmfw/src/entry.rs
+++ b/pvmfw/src/entry.rs
@@ -88,7 +88,7 @@
         kernel: usize,
         kernel_size: usize,
         vm_dtbo: Option<&mut [u8]>,
-        vm_base_dtbo: Option<&[u8]>,
+        vm_ref_dt: Option<&[u8]>,
     ) -> Result<Self, RebootReason> {
         let fdt_size = NonZeroUsize::new(crosvm::FDT_MAX_SIZE).unwrap();
         // TODO - Only map the FDT as read-only, until we modify it right before jump_to_payload()
@@ -102,7 +102,7 @@
         // SAFETY: The tracker validated the range to be in main memory, mapped, and not overlap.
         let fdt = unsafe { slice::from_raw_parts_mut(range.start as *mut u8, range.len()) };
 
-        let info = fdt::sanitize_device_tree(fdt, vm_dtbo, vm_base_dtbo)?;
+        let info = fdt::sanitize_device_tree(fdt, vm_dtbo, vm_ref_dt)?;
         let fdt = libfdt::Fdt::from_mut_slice(fdt).map_err(|e| {
             error!("Failed to load sanitized FDT: {e}");
             RebootReason::InvalidFdt
@@ -233,7 +233,7 @@
         payload,
         payload_size,
         config_entries.vm_dtbo,
-        config_entries.vm_base_dtbo,
+        config_entries.vm_ref_dt,
     )?;
 
     // This wrapper allows main() to be blissfully ignorant of platform details.
diff --git a/pvmfw/src/fdt.rs b/pvmfw/src/fdt.rs
index 33a5055..2ea4599 100644
--- a/pvmfw/src/fdt.rs
+++ b/pvmfw/src/fdt.rs
@@ -202,7 +202,7 @@
 }
 
 /// Read candidate properties' names from DT which could be overlaid
-fn parse_vm_base_dtbo(fdt: &Fdt) -> libfdt::Result<BTreeMap<CString, Vec<u8>>> {
+fn parse_vm_ref_dt(fdt: &Fdt) -> libfdt::Result<BTreeMap<CString, Vec<u8>>> {
     let mut property_map = BTreeMap::new();
     if let Some(avf_node) = fdt.node(cstr!("/avf"))? {
         for property in avf_node.properties()? {
@@ -217,29 +217,28 @@
     Ok(property_map)
 }
 
-/// Overlay VM base DTBO into VM DT based on the props_info. Property is overlaid in vm_dt only
-/// when it exists both in vm_base_dtbo and props_info. If the values mismatch, it returns error.
-fn apply_vm_base_dtbo(
+/// Overlay VM reference DT into VM DT based on the props_info. Property is overlaid in vm_dt only
+/// when it exists both in vm_ref_dt and props_info. If the values mismatch, it returns error.
+fn validate_vm_ref_dt(
     vm_dt: &mut Fdt,
-    vm_base_dtbo: &Fdt,
+    vm_ref_dt: &Fdt,
     props_info: &BTreeMap<CString, Vec<u8>>,
 ) -> libfdt::Result<()> {
     let mut root_vm_dt = vm_dt.root_mut()?;
     let mut avf_vm_dt = root_vm_dt.add_subnode(cstr!("avf"))?;
-    // TODO(b/318431677): Validate nodes beyond /fragment@0/__overlay__/avf and use apply_overlay.
-    let avf_vm_base_dtbo =
-        vm_base_dtbo.node(cstr!("/fragment@0/__overlay__/avf"))?.ok_or(FdtError::NotFound)?;
+    // TODO(b/318431677): Validate nodes beyond /avf.
+    let avf_node = vm_ref_dt.node(cstr!("/avf"))?.ok_or(FdtError::NotFound)?;
     for (name, value) in props_info.iter() {
-        if let Some(value_in_vm_base_dtbo) = avf_vm_base_dtbo.getprop(name)? {
-            if value != value_in_vm_base_dtbo {
+        if let Some(ref_value) = avf_node.getprop(name)? {
+            if value != ref_value {
                 error!(
-                    "Property mismatches while applying overlay VM base DTBO. \
-                    Name:{:?}, Value from host as hex:{:x?}, Value from VM base DTBO as hex:{:x?}",
-                    name, value, value_in_vm_base_dtbo
+                    "Property mismatches while applying overlay VM reference DT. \
+                    Name:{:?}, Value from host as hex:{:x?}, Value from VM reference DT as hex:{:x?}",
+                    name, value, ref_value
                 );
                 return Err(FdtError::BadValue);
             }
-            avf_vm_dt.setprop(name, value_in_vm_base_dtbo)?;
+            avf_vm_dt.setprop(name, ref_value)?;
         }
     }
     Ok(())
@@ -637,7 +636,7 @@
     serial_info: SerialInfo,
     pub swiotlb_info: SwiotlbInfo,
     device_assignment: Option<DeviceAssignmentInfo>,
-    vm_base_dtbo_props_info: BTreeMap<CString, Vec<u8>>,
+    vm_ref_dt_props_info: BTreeMap<CString, Vec<u8>>,
 }
 
 impl DeviceTreeInfo {
@@ -651,7 +650,7 @@
 pub fn sanitize_device_tree(
     fdt: &mut [u8],
     vm_dtbo: Option<&mut [u8]>,
-    vm_base_dtbo: Option<&[u8]>,
+    vm_ref_dt: Option<&[u8]>,
 ) -> Result<DeviceTreeInfo, RebootReason> {
     let fdt = Fdt::from_mut_slice(fdt).map_err(|e| {
         error!("Failed to load FDT: {e}");
@@ -695,14 +694,14 @@
         }
     }
 
-    if let Some(vm_base_dtbo) = vm_base_dtbo {
-        let vm_base_dtbo = Fdt::from_slice(vm_base_dtbo).map_err(|e| {
-            error!("Failed to load VM base DTBO: {e}");
+    if let Some(vm_ref_dt) = vm_ref_dt {
+        let vm_ref_dt = Fdt::from_slice(vm_ref_dt).map_err(|e| {
+            error!("Failed to load VM reference DT: {e}");
             RebootReason::InvalidFdt
         })?;
 
-        apply_vm_base_dtbo(fdt, vm_base_dtbo, &info.vm_base_dtbo_props_info).map_err(|e| {
-            error!("Failed to apply VM base DTBO: {e}");
+        validate_vm_ref_dt(fdt, vm_ref_dt, &info.vm_ref_dt_props_info).map_err(|e| {
+            error!("Failed to apply VM reference DT: {e}");
             RebootReason::InvalidFdt
         })?;
     }
@@ -780,7 +779,7 @@
         None => None,
     };
 
-    let vm_base_dtbo_props_info = parse_vm_base_dtbo(fdt).map_err(|e| {
+    let vm_ref_dt_props_info = parse_vm_ref_dt(fdt).map_err(|e| {
         error!("Failed to read names of properties under /avf from DT: {e}");
         RebootReason::InvalidFdt
     })?;
@@ -795,7 +794,7 @@
         serial_info,
         swiotlb_info,
         device_assignment,
-        vm_base_dtbo_props_info,
+        vm_ref_dt_props_info,
     })
 }