Actually derive microdroid vendor dice node

The derive_microdroid_vendor_dice_node binary gets the current dice
chain from the /dev/open-dice0 driver, derives the new dice chain with
the microdroid vendor node and writes it to the
/microdroid_resources/dice_chain.raw file.

The microdroid_manager will read the dice chain from
/microdroid_resources/dice_chain.raw and derive the final dice chain
with the payload node. After the derivation is done, microdroid_manager
will delete the /microdroid_resources/dice_chain.raw file.

Additionally, since /microdroid_resources is mounted in first_stage_init
which happens before selinux is configured, we also call the
restorecon_recursive /microdroid_resources before starting
microdroid_manager to make sure that the /microdroid_resources and
/microdroid_resources/dice_chain.raw have correct context.

Bug: 287593065
Test: run microdroid with vendor partition
Test: atest MicrodroidTests
Change-Id: Ibeb05b0ed24610624b11ac2c3e907cc900bd4cab
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 2386bd4..7da9ea4 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -43,6 +43,7 @@
 use log::{error, info};
 use microdroid_metadata::{Metadata, PayloadMetadata};
 use microdroid_payload_config::{ApkConfig, OsConfig, Task, TaskType, VmPayloadConfig};
+use nix::mount::{umount2, MntFlags};
 use nix::sys::signal::Signal;
 use payload::load_metadata;
 use rpcbinder::RpcSession;
@@ -86,6 +87,8 @@
 const ENCRYPTEDSTORE_BACKING_DEVICE: &str = "/dev/block/by-name/encryptedstore";
 const ENCRYPTEDSTORE_KEYSIZE: usize = 32;
 
+const DICE_CHAIN_FILE: &str = "/microdroid_resources/dice_chain.raw";
+
 #[derive(thiserror::Error, Debug)]
 enum MicrodroidError {
     #[error("Cannot connect to virtualization service: {0}")]
@@ -301,8 +304,13 @@
     vm_payload_service_fd: OwnedFd,
 ) -> Result<i32> {
     let metadata = load_metadata().context("Failed to load payload metadata")?;
-    let dice = DiceDriver::new(Path::new("/dev/open-dice0"), is_strict_boot())
-        .context("Failed to load DICE")?;
+    let dice = if Path::new(DICE_CHAIN_FILE).exists() {
+        DiceDriver::from_file(Path::new(DICE_CHAIN_FILE))
+            .context("Failed to load DICE from file")?
+    } else {
+        DiceDriver::new(Path::new("/dev/open-dice0"), is_strict_boot())
+            .context("Failed to load DICE from driver")?
+    };
 
     // Microdroid skips checking payload against instance image iff the device supports
     // secretkeeper. In that case Microdroid use VmSecret::V2, which provide protection against
@@ -328,6 +336,10 @@
 
         // Start apexd to activate APEXes. This may allow code within them to run.
         system_properties::write("ctl.start", "apexd-vm")?;
+
+        // Unmounting /microdroid_resources is a defence-in-depth effort to ensure that payload
+        // can't get hold of dice chain stored there.
+        umount2("/microdroid_resources", MntFlags::MNT_DETACH)?;
     }
 
     // Run encryptedstore binary to prepare the storage