Use fs-verity digests proto to build the directory
The proto contains path -> digest mapping. In this change, we start to
use the provided protobuf to build the directory. Digest is not yet
used.
Bug: 206869687
Test: atest AuthFsHostTest ComposHostTestCases MicrodroidTestCase
Change-Id: I0f03219c1243f20f9ec5099a451c6f588add9608
diff --git a/authfs/Android.bp b/authfs/Android.bp
index 471b0cf..ef78d4e 100644
--- a/authfs/Android.bp
+++ b/authfs/Android.bp
@@ -18,10 +18,12 @@
"libbinder_rpc_unstable_bindgen",
"libbinder_rs",
"libcfg_if",
+ "libfsverity_digests_proto_rust",
"libfuse_rust",
"liblibc",
"liblog_rust",
"libnix",
+ "libprotobuf",
"libstructopt",
"libthiserror",
],
diff --git a/authfs/service/src/authfs.rs b/authfs/service/src/authfs.rs
index e1d820a..c941360 100644
--- a/authfs/service/src/authfs.rs
+++ b/authfs/service/src/authfs.rs
@@ -152,7 +152,6 @@
}
for conf in in_dir_fds {
args.push(OsString::from("--remote-ro-dir"));
- // TODO(206869687): Replace /dev/null with the real path when possible.
args.push(OsString::from(format!("{}:{}:{}", conf.fd, conf.manifestPath, conf.prefix)));
}
for conf in out_dir_fds {
diff --git a/authfs/src/main.rs b/authfs/src/main.rs
index 18b7b51..0fa3db7 100644
--- a/authfs/src/main.rs
+++ b/authfs/src/main.rs
@@ -27,9 +27,11 @@
//! of the actual file name, the exposed file names through AuthFS are currently integer, e.g.
//! /mountpoint/42.
-use anyhow::{bail, Result};
+use anyhow::{anyhow, bail, Result};
use log::error;
+use protobuf::Message;
use std::convert::TryInto;
+use std::fs::File;
use std::path::{Path, PathBuf};
use structopt::StructOpt;
@@ -47,6 +49,7 @@
};
use fsstat::RemoteFsStatsReader;
use fsverity::{VerifiedFileEditor, VerifiedFileReader};
+use fsverity_digests_proto::fsverity_digests::FSVerityDigests;
use fusefs::{AuthFs, AuthFsEntry};
#[derive(StructOpt)]
@@ -93,10 +96,10 @@
/// remote host may be included in the mapping file, so the directory view may be partial. The
/// directory structure won't change throughout the filesystem lifetime.
///
- /// For example, `--remote-ro-dir 5:/path/to/mapping:/prefix/` tells the filesystem to
+ /// For example, `--remote-ro-dir 5:/path/to/mapping:prefix/` tells the filesystem to
/// construct a directory structure defined in the mapping file at $MOUNTPOINT/5, which may
- /// include a file like /5/system/framework/framework.jar. "/prefix/" tells the filesystem to
- /// strip the path (e.g. "/system/") from the mount point to match the expected location of the
+ /// include a file like /5/system/framework/framework.jar. "prefix/" tells the filesystem to
+ /// strip the path (e.g. "system/") from the mount point to match the expected location of the
/// remote FD (e.g. a directory FD of "/system" in the remote).
#[structopt(long, parse(try_from_str = parse_remote_new_ro_dir_option))]
remote_ro_dir: Vec<OptionRemoteRoDir>,
@@ -131,11 +134,9 @@
/// A mapping file that describes the expecting file/directory structure and integrity metadata
/// in the remote directory. The file contains serialized protobuf of
/// android.security.fsverity.FSVerityDigests.
- /// TODO(206869687): Really use the file when it's generated.
- #[allow(dead_code)]
mapping_file_path: PathBuf,
- prefix: PathBuf,
+ prefix: String,
}
fn parse_remote_ro_file_option(option: &str) -> Result<OptionRemoteRoFile> {
@@ -157,7 +158,7 @@
Ok(OptionRemoteRoDir {
remote_dir_fd: strs[0].parse::<i32>().unwrap(),
mapping_file_path: PathBuf::from(strs[1]),
- prefix: PathBuf::from(strs[2]),
+ prefix: String::from(strs[2]),
})
}
@@ -260,42 +261,25 @@
AuthFsEntry::ReadonlyDirectory { dir: InMemoryDir::new() },
)?;
- // TODO(206869687): Read actual path from config.mapping_file_path when it's generated.
- let paths = vec![
- Path::new("/system/framework/com.android.location.provider.jar"),
- Path::new("/system/framework/ethernet-service.jar"),
- Path::new("/system/framework/ext.jar"),
- Path::new("/system/framework/framework-graphics.jar"),
- Path::new("/system/framework/framework.jar"),
- Path::new("/system/framework/ims-common.jar"),
- Path::new("/system/framework/services.jar"),
- Path::new("/system/framework/services.jar.prof"),
- Path::new("/system/framework/telephony-common.jar"),
- Path::new("/system/framework/voip-common.jar"),
- Path::new("/system/etc/boot-image.prof"),
- Path::new("/system/etc/classpaths/bootclasspath.pb"),
- Path::new("/system/etc/classpaths/systemserverclasspath.pb"),
- Path::new("/system/etc/dirty-image-objects"),
- ];
-
- for path in &paths {
+ // Build the directory tree based on the mapping file.
+ let mut reader = File::open(&config.mapping_file_path)?;
+ let proto = FSVerityDigests::parse_from_reader(&mut reader)?;
+ for path_str in proto.digests.keys() {
let file_entry = {
+ let remote_path_str = path_str.strip_prefix(&config.prefix).ok_or_else(|| {
+ anyhow!("Expect path {} to match prefix {}", path_str, config.prefix)
+ })?;
// TODO(205883847): Not all files will be used. Open the remote file lazily.
- let related_path = path.strip_prefix(&config.prefix)?;
let remote_file = RemoteFileReader::new_by_path(
service.clone(),
config.remote_dir_fd,
- related_path,
+ Path::new(remote_path_str),
)?;
let file_size = service.getFileSize(remote_file.get_remote_fd())?.try_into()?;
// TODO(206869687): Switch to VerifiedReadonly
AuthFsEntry::UnverifiedReadonly { reader: remote_file, file_size }
};
- authfs.add_entry_at_ro_dir_by_path(
- dir_root_inode,
- path.strip_prefix("/")?,
- file_entry,
- )?;
+ authfs.add_entry_at_ro_dir_by_path(dir_root_inode, Path::new(path_str), file_entry)?;
}
}
diff --git a/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java b/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
index 819061b..ef544b2 100644
--- a/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
+++ b/authfs/tests/java/src/com/android/fs/AuthFsHostTest.java
@@ -70,6 +70,14 @@
/** Path to authfs on Microdroid */
private static final String AUTHFS_BIN = "/system/bin/authfs";
+ /** Idsig paths to be created for each APK in the "extra_apks" of vm_config.json. */
+ private static final String[] EXTRA_IDSIG_PATHS = new String[] {
+ TEST_DIR + "BuildManifest.apk.idsig",
+ };
+
+ /** Build manifest path in the VM. 0 is the index of extra_apks in vm_config.json. */
+ private static final String BUILD_MANIFEST_PATH = "/mnt/extra-apk/0/assets/build_manifest.pb";
+
/** Plenty of time for authfs to get ready */
private static final int AUTHFS_INIT_TIMEOUT_MS = 3000;
@@ -111,13 +119,14 @@
CLog.i("Starting the shared VM");
final String apkName = "MicrodroidTestApp.apk";
final String packageName = "com.android.microdroid.test";
- final String configPath = "assets/vm_config.json"; // path inside the APK
+ final String configPath = "assets/vm_config_extra_apk.json"; // path inside the APK
sCid =
startMicrodroid(
androidDevice,
testInfo.getBuildInfo(),
apkName,
packageName,
+ EXTRA_IDSIG_PATHS,
configPath,
/* debug */ true,
/* use default memoryMib */ 0,
@@ -491,9 +500,8 @@
// Setup
String authfsInputDir = MOUNT_DIR + "/3";
runFdServerOnAndroid("--open-dir 3:/system", "--ro-dirs 3");
- // TODO(206869687): Replace /dev/null with real manifest file when it's generated. We
- // currently hard-coded the files for the test manually, and ignore the integrity check.
- runAuthFsOnMicrodroid("--remote-ro-dir 3:/dev/null:/system --cid " + VMADDR_CID_HOST);
+ runAuthFsOnMicrodroid("--remote-ro-dir 3:" + BUILD_MANIFEST_PATH + ":system/ --cid "
+ + VMADDR_CID_HOST);
// Action
String actualHash =
@@ -509,9 +517,8 @@
// Setup
String authfsInputDir = MOUNT_DIR + "/3";
runFdServerOnAndroid("--open-dir 3:/system", "--ro-dirs 3");
- // TODO(206869687): Replace /dev/null with real manifest file when it's generated. We
- // currently hard-coded the files for the test manually, and ignore the integrity check.
- runAuthFsOnMicrodroid("--remote-ro-dir 3:/dev/null:/system --cid " + VMADDR_CID_HOST);
+ runAuthFsOnMicrodroid("--remote-ro-dir 3:" + BUILD_MANIFEST_PATH + ":system/ --cid "
+ + VMADDR_CID_HOST);
// Verify
runOnMicrodroid("test -f " + authfsInputDir + "/system/framework/services.jar");
diff --git a/compos/src/compilation.rs b/compos/src/compilation.rs
index 4837029..9a23bf5 100644
--- a/compos/src/compilation.rs
+++ b/compos/src/compilation.rs
@@ -122,9 +122,9 @@
port: FD_SERVER_PORT,
inputDirFdAnnotations: vec![InputDirFdAnnotation {
fd: context.system_dir_fd,
- // TODO(206869687): Replace /dev/null with the real path when possible.
- manifestPath: "/dev/null".to_string(),
- prefix: "/system".to_string(),
+ // 0 is the index of extra_apks in vm_config_extra_apk.json
+ manifestPath: "/mnt/extra-apk/0/assets/build_manifest.pb".to_string(),
+ prefix: "system/".to_string(),
}],
outputDirFdAnnotations: vec![
OutputDirFdAnnotation { fd: context.output_dir_fd },
diff --git a/compos/tests/java/android/compos/test/ComposKeyTestCase.java b/compos/tests/java/android/compos/test/ComposKeyTestCase.java
index d7c0058..d59d3d9 100644
--- a/compos/tests/java/android/compos/test/ComposKeyTestCase.java
+++ b/compos/tests/java/android/compos/test/ComposKeyTestCase.java
@@ -41,9 +41,12 @@
/** Wait time for service to be ready on boot */
private static final int READY_LATENCY_MS = 10 * 1000; // 10 seconds
- // Path to compos_key_cmd tool
+ /** Path to compos_key_cmd tool */
private static final String COMPOS_KEY_CMD_BIN = "/apex/com.android.compos/bin/compos_key_cmd";
+ /** Config of the test VM. This is a path inside the APK. */
+ private static final String VM_TEST_CONFIG_PATH = "assets/vm_test_config.json";
+
private String mCid;
@Before
@@ -132,7 +135,7 @@
getBuild(),
/* apkName, no need to install */ null,
packageName,
- "assets/vm_test_config.json",
+ VM_TEST_CONFIG_PATH,
/* debug */ true,
/* use default memoryMib */ 0,
Optional.empty(),
diff --git a/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java b/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
index 528f7c2..678fe84 100644
--- a/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
+++ b/tests/hostside/helper/java/android/virt/test/VirtualizationTestCaseBase.java
@@ -33,6 +33,7 @@
import java.io.File;
import java.io.FileNotFoundException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
@@ -187,6 +188,22 @@
Optional<Integer> numCpus,
Optional<String> cpuAffinity)
throws DeviceNotAvailableException {
+ return startMicrodroid(androidDevice, buildInfo, apkName, packageName, null, configPath,
+ debug, memoryMib, numCpus, cpuAffinity);
+ }
+
+ public static String startMicrodroid(
+ ITestDevice androidDevice,
+ IBuildInfo buildInfo,
+ String apkName,
+ String packageName,
+ String[] extraIdsigPaths,
+ String configPath,
+ boolean debug,
+ int memoryMib,
+ Optional<Integer> numCpus,
+ Optional<String> cpuAffinity)
+ throws DeviceNotAvailableException {
CommandRunner android = new CommandRunner(androidDevice);
// Install APK if necessary
@@ -212,20 +229,26 @@
final String debugFlag = debug ? "--debug full" : "";
// Run the VM
- String ret =
- android.run(
- VIRT_APEX + "bin/vm",
- "run-app",
- "--daemonize",
- "--log " + logPath,
- "--mem " + memoryMib,
- numCpus.isPresent() ? "--cpus " + numCpus.get() : "",
- cpuAffinity.isPresent() ? "--cpu-affinity " + cpuAffinity.get() : "",
- debugFlag,
- apkPath,
- outApkIdsigPath,
- instanceImg,
- configPath);
+ ArrayList<String> args = new ArrayList<>(Arrays.asList(
+ VIRT_APEX + "bin/vm",
+ "run-app",
+ "--daemonize",
+ "--log " + logPath,
+ "--mem " + memoryMib,
+ numCpus.isPresent() ? "--cpus " + numCpus.get() : "",
+ cpuAffinity.isPresent() ? "--cpu-affinity " + cpuAffinity.get() : "",
+ debugFlag,
+ apkPath,
+ outApkIdsigPath,
+ instanceImg,
+ configPath));
+ if (extraIdsigPaths != null) {
+ for (String path : extraIdsigPaths) {
+ args.add("--extra-idsig");
+ args.add(path);
+ }
+ }
+ String ret = android.run(args.toArray(new String[0]));
// Redirect log.txt to logd using logwrapper
ExecutorService executor = Executors.newFixedThreadPool(1);
diff --git a/tests/testapk/assets/vm_config_extra_apk.json b/tests/testapk/assets/vm_config_extra_apk.json
new file mode 100644
index 0000000..a5bae63
--- /dev/null
+++ b/tests/testapk/assets/vm_config_extra_apk.json
@@ -0,0 +1,18 @@
+{
+ "os": {
+ "name": "microdroid"
+ },
+ "task": {
+ "type": "microdroid_launcher",
+ "command": "MicrodroidTestNativeLib.so",
+ "args": [
+ "hello",
+ "microdroid"
+ ]
+ },
+ "extra_apks": [
+ {
+ "path": "/system/etc/security/fsverity/BuildManifest.apk"
+ }
+ ]
+}
diff --git a/vm/src/main.rs b/vm/src/main.rs
index a466a4c..ad8c201 100644
--- a/vm/src/main.rs
+++ b/vm/src/main.rs
@@ -86,7 +86,7 @@
cpu_affinity: Option<String>,
/// Paths to extra idsig files.
- #[structopt(long)]
+ #[structopt(long = "extra-idsig")]
extra_idsigs: Vec<PathBuf>,
},
/// Run a virtual machine