Make BuildManifest.apk available in CompOS

Bug: 206869687
Test: See /mnt/extra-apk/0/assets/build_manifest in the VM
Change-Id: Ieb687804a5d8d9df9ec8ab565b006d53e6ad6363
diff --git a/compos/apk/assets/vm_config.json b/compos/apk/assets/vm_config.json
index 0e97228..260332e 100644
--- a/compos/apk/assets/vm_config.json
+++ b/compos/apk/assets/vm_config.json
@@ -10,6 +10,11 @@
       "--log_to_stderr"
     ]
   },
+  "extra_apks": [
+    {
+      "path": "/system/etc/security/fsverity/BuildManifest.apk"
+    }
+  ],
   "apexes": [
     {
       "name": "com.android.art"
diff --git a/compos/apk/assets/vm_config_staged.json b/compos/apk/assets/vm_config_staged.json
index 5820982..1affa79 100644
--- a/compos/apk/assets/vm_config_staged.json
+++ b/compos/apk/assets/vm_config_staged.json
@@ -11,6 +11,11 @@
     ]
   },
   "prefer_staged": true,
+  "extra_apks": [
+    {
+      "path": "/system/etc/security/fsverity/BuildManifest.apk"
+    }
+  ],
   "apexes": [
     {
       "name": "com.android.art"
diff --git a/compos/common/compos_client.rs b/compos/common/compos_client.rs
index 3bb066f..4216e1a 100644
--- a/compos/common/compos_client.rs
+++ b/compos/common/compos_client.rs
@@ -73,6 +73,7 @@
         service: &dyn IVirtualizationService,
         instance_image: File,
         idsig: &Path,
+        idsig_manifest_apk: &Path,
         parameters: &VmParameters,
     ) -> Result<VmInstance> {
         let instance_fd = ParcelFileDescriptor::new(instance_image);
@@ -83,19 +84,12 @@
         let apk_fd = File::open(apex_dir.join("app/CompOSPayloadApp/CompOSPayloadApp.apk"))
             .context("Failed to open config APK file")?;
         let apk_fd = ParcelFileDescriptor::new(apk_fd);
+        let idsig_fd = prepare_idsig(service, &apk_fd, idsig)?;
 
-        if !idsig.exists() {
-            // Prepare idsig file via VirtualizationService
-            let idsig_file = File::create(idsig).context("Failed to create idsig file")?;
-            let idsig_fd = ParcelFileDescriptor::new(idsig_file);
-            service
-                .createOrUpdateIdsigFile(&apk_fd, &idsig_fd)
-                .context("Failed to update idsig file")?;
-        }
-
-        // Open idsig as read-only
-        let idsig_file = File::open(idsig).context("Failed to open idsig file")?;
-        let idsig_fd = ParcelFileDescriptor::new(idsig_file);
+        let manifest_apk_fd = File::open("/system/etc/security/fsverity/BuildManifest.apk")
+            .context("Failed to open build manifest APK file")?;
+        let manifest_apk_fd = ParcelFileDescriptor::new(manifest_apk_fd);
+        let idsig_manifest_apk_fd = prepare_idsig(service, &manifest_apk_fd, idsig_manifest_apk)?;
 
         let (console_fd, log_fd, debug_level) = if parameters.debug_mode {
             // Console output and the system log output from the VM are redirected to file.
@@ -117,6 +111,7 @@
             instanceImage: Some(instance_fd),
             configPath: config_path.to_owned(),
             debugLevel: debug_level,
+            extraIdsigs: vec![idsig_manifest_apk_fd],
             ..Default::default()
         });
 
@@ -165,6 +160,26 @@
     }
 }
 
+fn prepare_idsig(
+    service: &dyn IVirtualizationService,
+    apk_fd: &ParcelFileDescriptor,
+    idsig_path: &Path,
+) -> Result<ParcelFileDescriptor> {
+    if !idsig_path.exists() {
+        // Prepare idsig file via VirtualizationService
+        let idsig_file = File::create(idsig_path).context("Failed to create idsig file")?;
+        let idsig_fd = ParcelFileDescriptor::new(idsig_file);
+        service
+            .createOrUpdateIdsigFile(apk_fd, &idsig_fd)
+            .context("Failed to update idsig file")?;
+    }
+
+    // Open idsig as read-only
+    let idsig_file = File::open(idsig_path).context("Failed to open idsig file")?;
+    let idsig_fd = ParcelFileDescriptor::new(idsig_file);
+    Ok(idsig_fd)
+}
+
 struct VsockFactory<'a> {
     vm: &'a dyn IVirtualMachine,
 }
diff --git a/compos/common/lib.rs b/compos/common/lib.rs
index 9a4d0e3..66ce8cb 100644
--- a/compos/common/lib.rs
+++ b/compos/common/lib.rs
@@ -58,6 +58,10 @@
 /// The file that holds the idsig for the CompOS Payload APK.
 pub const IDSIG_FILE: &str = "idsig";
 
+/// The file that holds the idsig for the build manifest APK (that makes enumerated files from
+/// /system available in CompOS).
+pub const IDSIG_MANIFEST_APK_FILE: &str = "idsig_manifest_apk";
+
 /// The path within our config APK of our default VM configuration file, used at boot time.
 pub const DEFAULT_VM_CONFIG_PATH: &str = "assets/vm_config.json";
 
diff --git a/compos/composd/src/instance_starter.rs b/compos/composd/src/instance_starter.rs
index 6946c11..4fed98a 100644
--- a/compos/composd/src/instance_starter.rs
+++ b/compos/composd/src/instance_starter.rs
@@ -26,7 +26,8 @@
 use compos_aidl_interface::binder::{ParcelFileDescriptor, Strong};
 use compos_common::compos_client::{VmInstance, VmParameters};
 use compos_common::{
-    COMPOS_DATA_ROOT, IDSIG_FILE, INSTANCE_IMAGE_FILE, PRIVATE_KEY_BLOB_FILE, PUBLIC_KEY_FILE,
+    COMPOS_DATA_ROOT, IDSIG_FILE, IDSIG_MANIFEST_APK_FILE, INSTANCE_IMAGE_FILE,
+    PRIVATE_KEY_BLOB_FILE, PUBLIC_KEY_FILE,
 };
 use log::{info, warn};
 use std::fs;
@@ -51,6 +52,7 @@
     instance_root: PathBuf,
     instance_image: PathBuf,
     idsig: PathBuf,
+    idsig_manifest_apk: PathBuf,
     key_blob: PathBuf,
     public_key: PathBuf,
     vm_parameters: VmParameters,
@@ -62,6 +64,7 @@
         let instance_root_path = instance_root.as_path();
         let instance_image = instance_root_path.join(INSTANCE_IMAGE_FILE);
         let idsig = instance_root_path.join(IDSIG_FILE);
+        let idsig_manifest_apk = instance_root_path.join(IDSIG_MANIFEST_APK_FILE);
         let key_blob = instance_root_path.join(PRIVATE_KEY_BLOB_FILE);
         let public_key = instance_root_path.join(PUBLIC_KEY_FILE);
         Self {
@@ -69,6 +72,7 @@
             instance_root,
             instance_image,
             idsig,
+            idsig_manifest_apk,
             key_blob,
             public_key,
             vm_parameters,
@@ -125,8 +129,9 @@
         let _ = fs::create_dir(&self.instance_root);
 
         self.create_instance_image(virtualization_service)?;
-        // Delete existing idsig file. Ignore error in case idsig doesn't exist.
+        // Delete existing idsig files. Ignore error in case idsig doesn't exist.
         let _ = fs::remove_file(&self.idsig);
+        let _ = fs::remove_file(&self.idsig_manifest_apk);
 
         let compos_instance = self.start_vm(virtualization_service)?;
         let service = &compos_instance.service;
@@ -161,6 +166,7 @@
             virtualization_service,
             instance_image,
             &self.idsig,
+            &self.idsig_manifest_apk,
             &self.vm_parameters,
         )
         .context("Starting VM")?;
diff --git a/compos/verify_key/verify_key.rs b/compos/verify_key/verify_key.rs
index a028264..13d3c8b 100644
--- a/compos/verify_key/verify_key.rs
+++ b/compos/verify_key/verify_key.rs
@@ -21,8 +21,9 @@
 use compos_aidl_interface::binder::ProcessState;
 use compos_common::compos_client::{VmInstance, VmParameters};
 use compos_common::{
-    COMPOS_DATA_ROOT, CURRENT_INSTANCE_DIR, IDSIG_FILE, INSTANCE_IMAGE_FILE, PENDING_INSTANCE_DIR,
-    PRIVATE_KEY_BLOB_FILE, PUBLIC_KEY_FILE, TEST_INSTANCE_DIR,
+    COMPOS_DATA_ROOT, CURRENT_INSTANCE_DIR, IDSIG_FILE, IDSIG_MANIFEST_APK_FILE,
+    INSTANCE_IMAGE_FILE, PENDING_INSTANCE_DIR, PRIVATE_KEY_BLOB_FILE, PUBLIC_KEY_FILE,
+    TEST_INSTANCE_DIR,
 };
 use std::fs::{self, File};
 use std::io::Read;
@@ -100,6 +101,7 @@
     let public_key = instance_dir.join(PUBLIC_KEY_FILE);
     let instance_image = instance_dir.join(INSTANCE_IMAGE_FILE);
     let idsig = instance_dir.join(IDSIG_FILE);
+    let idsig_manifest_apk = instance_dir.join(IDSIG_MANIFEST_APK_FILE);
 
     let blob = read_small_file(blob).context("Failed to read key blob")?;
     let public_key = read_small_file(public_key).context("Failed to read public key")?;
@@ -110,6 +112,7 @@
         &*virtualization_service,
         instance_image,
         &idsig,
+        &idsig_manifest_apk,
         &VmParameters { debug_mode, ..Default::default() },
     )?;
     let service = vm_instance.get_service()?;