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");