Merge "Run apk mount utils from microdroid_manager"
diff --git a/apkdmverity/Android.bp b/apkdmverity/Android.bp
index e6b1ca9..403e726 100644
--- a/apkdmverity/Android.bp
+++ b/apkdmverity/Android.bp
@@ -14,6 +14,7 @@
         "libclap",
         "libdata_model",
         "libidsig",
+        "libitertools",
         "liblibc",
         "libnix",
         "libnum_traits",
@@ -32,7 +33,6 @@
 rust_binary {
     name: "apkdmverity",
     defaults: ["apkdmverity.defaults"],
-    init_rc: ["apkdmverity.rc"],
     bootstrap: true,
 }
 
diff --git a/apkdmverity/apkdmverity.rc b/apkdmverity/apkdmverity.rc
deleted file mode 100644
index c6ef52b..0000000
--- a/apkdmverity/apkdmverity.rc
+++ /dev/null
@@ -1,3 +0,0 @@
-service apkdmverity /system/bin/apkdmverity /dev/block/by-name/microdroid-apk /dev/block/by-name/microdroid-apk-idsig microdroid-apk
-    disabled
-    oneshot
diff --git a/apkdmverity/src/main.rs b/apkdmverity/src/main.rs
index b240c85..a8a8f15 100644
--- a/apkdmverity/src/main.rs
+++ b/apkdmverity/src/main.rs
@@ -28,6 +28,7 @@
 use anyhow::{bail, Context, Result};
 use clap::{App, Arg};
 use idsig::{HashAlgorithm, V4Signature};
+use itertools::Itertools;
 use rustutils::system_properties;
 use std::fmt::Debug;
 use std::fs;
@@ -38,42 +39,35 @@
 fn main() -> Result<()> {
     let matches = App::new("apkdmverity")
         .about("Creates a dm-verity block device out of APK signed with APK signature scheme V4.")
-        .arg(
-            Arg::with_name("apk")
-                .help("Input APK file. Must be signed using the APK signature scheme V4.")
-                .required(true),
-        )
-        .arg(
-            Arg::with_name("idsig")
-                .help("The idsig file having the merkle tree and the signing info.")
-                .required(true),
-        )
-        .arg(
-            Arg::with_name("name")
-                .help(
-                    "Name of the dm-verity block device. The block device is created at \
-                      \"/dev/mapper/<name>\".",
-                )
-                .required(true),
-        )
+        .arg(Arg::from_usage(
+            "--apk... <apk_path> <idsig_path> <name> \
+                            'Input APK file, idsig file, and the name of the block device. The APK \
+                            file must be signed using the APK signature scheme 4. The block device \
+                            is created at \"/dev/mapper/<name>\".'",
+        ))
         .arg(Arg::with_name("verbose").short("v").long("verbose").help("Shows verbose output"))
         .get_matches();
 
-    let apk = matches.value_of("apk").unwrap();
-    let idsig = matches.value_of("idsig").unwrap();
-    let name = matches.value_of("name").unwrap();
+    let apks = matches.values_of("apk").unwrap();
+    assert!(apks.len() % 3 == 0);
+
     let roothash = if let Ok(val) = system_properties::read("microdroid_manager.apk_root_hash") {
         Some(util::parse_hexstring(&val)?)
     } else {
         // This failure is not an error. We will use the roothash read from the idsig file.
         None
     };
-    let ret = enable_verity(apk, idsig, name, roothash.as_deref())?;
-    if matches.is_present("verbose") {
-        println!(
-            "data_device: {:?}, hash_device: {:?}, mapper_device: {:?}",
-            ret.data_device, ret.hash_device, ret.mapper_device
-        );
+
+    let verbose = matches.is_present("verbose");
+
+    for (apk, idsig, name) in apks.tuples() {
+        let ret = enable_verity(apk, idsig, name, roothash.as_deref())?;
+        if verbose {
+            println!(
+                "data_device: {:?}, hash_device: {:?}, mapper_device: {:?}",
+                ret.data_device, ret.hash_device, ret.mapper_device
+            );
+        }
     }
     Ok(())
 }
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 2e6fa36..99ebc51 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -33,7 +33,7 @@
 use std::fs::{self, File, OpenOptions};
 use std::os::unix::io::{FromRawFd, IntoRawFd};
 use std::path::Path;
-use std::process::{Command, Stdio};
+use std::process::{Child, Command, Stdio};
 use std::str;
 use std::time::{Duration, SystemTime};
 use vsock::VsockStream;
@@ -43,7 +43,16 @@
 };
 
 const WAIT_TIMEOUT: Duration = Duration::from_secs(10);
+const APK_DM_VERITY_ARGUMENT: ApkDmverityArgument = {
+    ApkDmverityArgument {
+        apk: "/dev/block/by-name/microdroid-apk",
+        idsig: "/dev/block/by-name/microdroid-apk-idsig",
+        name: "microdroid-apk",
+    }
+};
 const DM_MOUNTED_APK_PATH: &str = "/dev/block/mapper/microdroid-apk";
+const APKDMVERITY_BIN: &str = "/system/bin/apkdmverity";
+const ZIPFUSE_BIN: &str = "/system/bin/zipfuse";
 
 /// The CID representing the host VM
 const VMADDR_CID_HOST: u32 = 2;
@@ -135,7 +144,12 @@
     }
 
     // Before reading a file from the APK, start zipfuse
-    system_properties::write("ctl.start", "zipfuse")?;
+    run_zipfuse(
+        "fscontext=u:object_r:zipfusefs:s0,context=u:object_r:system_file:s0",
+        Path::new("/dev/block/mapper/microdroid-apk"),
+        Path::new("/mnt/apk"),
+    )
+    .context("Failed to run zipfuse")?;
 
     if !metadata.payload_config_path.is_empty() {
         let config = load_config(Path::new(&metadata.payload_config_path))?;
@@ -160,6 +174,37 @@
     Ok(())
 }
 
+struct ApkDmverityArgument<'a> {
+    apk: &'a str,
+    idsig: &'a str,
+    name: &'a str,
+}
+
+fn run_apkdmverity(args: &[ApkDmverityArgument]) -> Result<Child> {
+    let mut cmd = Command::new(APKDMVERITY_BIN);
+
+    cmd.stdin(Stdio::null()).stdout(Stdio::null()).stderr(Stdio::null());
+
+    for argument in args {
+        cmd.arg("--apk").arg(argument.apk).arg(argument.idsig).arg(argument.name);
+    }
+
+    cmd.spawn().context("Spawn apkdmverity")
+}
+
+fn run_zipfuse(option: &str, zip_path: &Path, mount_dir: &Path) -> Result<Child> {
+    Command::new(ZIPFUSE_BIN)
+        .arg("-o")
+        .arg(option)
+        .arg(zip_path)
+        .arg(mount_dir)
+        .stdin(Stdio::null())
+        .stdout(Stdio::null())
+        .stderr(Stdio::null())
+        .spawn()
+        .context("Spawn zipfuse")
+}
+
 // Verify payload before executing it. For APK payload, Full verification (which is slow) is done
 // when the root_hash values from the idsig file and the instance disk are different. This function
 // returns the verified root hash (for APK payload) and pubkeys (for APEX payloads) that can be
@@ -182,7 +227,7 @@
     }
 
     // Start apkdmverity and wait for the dm-verify block
-    system_properties::write("ctl.start", "apkdmverity")?;
+    let mut apkdmverity_child = run_apkdmverity(&[APK_DM_VERITY_ARGUMENT])?;
 
     // While waiting for apkdmverity to mount APK, gathers public keys and root digests from
     // APEX payload.
@@ -206,7 +251,8 @@
     // Start apexd to activate APEXes
     system_properties::write("ctl.start", "apexd-vm")?;
 
-    ioutil::wait_for_file(DM_MOUNTED_APK_PATH, WAIT_TIMEOUT)?;
+    // TODO(inseob): add timeout
+    apkdmverity_child.wait()?;
 
     // Do the full verification if the root_hash is un-trustful. This requires the full scanning of
     // the APK file and therefore can be very slow if the APK is large. Note that this step is
diff --git a/zipfuse/Android.bp b/zipfuse/Android.bp
index 79e6bad..e10fc31 100644
--- a/zipfuse/Android.bp
+++ b/zipfuse/Android.bp
@@ -28,7 +28,6 @@
 rust_binary {
     name: "zipfuse",
     defaults: ["zipfuse.defaults"],
-    init_rc: ["zipfuse.rc"],
     bootstrap: true,
 }
 
diff --git a/zipfuse/zipfuse.rc b/zipfuse/zipfuse.rc
deleted file mode 100644
index 1905705..0000000
--- a/zipfuse/zipfuse.rc
+++ /dev/null
@@ -1,2 +0,0 @@
-service zipfuse /system/bin/zipfuse -o fscontext=u:object_r:zipfusefs:s0,context=u:object_r:system_file:s0 /dev/block/mapper/microdroid-apk /mnt/apk
-    disabled