Use fsverity metadata file for authfs
Instead of alternative signature and merkle tree, authfs will use
.fsv_meta files, which are installed to the system partition with
PRODUCT_SYSTEM_FSVERITY_GENERATE_METADATA Makefile.
Bug: 205987437
Test: atest ComposHostTestCases AuthFsTestCase
Test: run "atest ." inside authfs/tests
Change-Id: Ia9db78663e0e322c7a59305c67ac5b84716d8efe
diff --git a/authfs/fd_server/src/aidl.rs b/authfs/fd_server/src/aidl.rs
index c2206c8..125b991 100644
--- a/authfs/fd_server/src/aidl.rs
+++ b/authfs/fd_server/src/aidl.rs
@@ -38,6 +38,9 @@
use authfs_aidl_interface::binder::{
BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Status, StatusCode, Strong,
};
+use authfs_fsverity_metadata::{
+ get_fsverity_metadata_path, parse_fsverity_metadata, FSVerityMetadata,
+};
use binder_common::{new_binder_exception, new_binder_service_specific_error};
/// Bitflags of forbidden file mode, e.g. setuid, setgid and sticky bit.
@@ -51,13 +54,8 @@
/// The file to read from. fs-verity metadata can be retrieved from this file's FD.
file: File,
- /// Alternative Merkle tree stored in another file.
- /// TODO(205987437): Replace with .fsv_meta file.
- alt_merkle_tree: Option<File>,
-
- /// Alternative signature stored in another file.
- /// TODO(205987437): Replace with .fsv_meta file.
- alt_signature: Option<File>,
+ // Alternative metadata storing merkle tree and signature.
+ alt_metadata: Option<Box<FSVerityMetadata>>,
},
/// A readable/writable file to serve by this server. This backing file should just be a
@@ -139,23 +137,23 @@
let offset: u64 = validate_and_cast_offset(offset)?;
self.handle_fd(id, |config| match config {
- FdConfig::Readonly { file, alt_merkle_tree, .. } => {
- if let Some(tree_file) = &alt_merkle_tree {
- read_into_buf(tree_file, size, offset).map_err(|e| {
+ FdConfig::Readonly { file, alt_metadata, .. } => {
+ let mut buf = vec![0; size];
+
+ let s = if let Some(metadata) = &alt_metadata {
+ metadata.read_merkle_tree(offset, &mut buf).map_err(|e| {
error!("readFsverityMerkleTree: read error: {}", e);
new_errno_error(Errno::EIO)
- })
+ })?
} else {
- let mut buf = vec![0; size];
- let s = fsverity::read_merkle_tree(file.as_raw_fd(), offset, &mut buf)
- .map_err(|e| {
- error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
- new_errno_error(Errno::EIO)
- })?;
- debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
- buf.truncate(s);
- Ok(buf)
- }
+ fsverity::read_merkle_tree(file.as_raw_fd(), offset, &mut buf).map_err(|e| {
+ error!("readFsverityMerkleTree: failed to retrieve merkle tree: {}", e);
+ new_errno_error(Errno::EIO)
+ })?
+ };
+ debug_assert!(s <= buf.len(), "Shouldn't return more bytes than asked");
+ buf.truncate(s);
+ Ok(buf)
}
FdConfig::ReadWrite(_file) => {
// For a writable file, Merkle tree is not expected to be served since Auth FS
@@ -169,15 +167,16 @@
fn readFsveritySignature(&self, id: i32) -> BinderResult<Vec<u8>> {
self.handle_fd(id, |config| match config {
- FdConfig::Readonly { file, alt_signature, .. } => {
- if let Some(sig_file) = &alt_signature {
- // Supposedly big enough buffer size to store signature.
- let size = MAX_REQUESTING_DATA as usize;
- let offset = 0;
- read_into_buf(sig_file, size, offset).map_err(|e| {
- error!("readFsveritySignature: read error: {}", e);
- new_errno_error(Errno::EIO)
- })
+ FdConfig::Readonly { file, alt_metadata, .. } => {
+ if let Some(metadata) = &alt_metadata {
+ if let Some(signature) = &metadata.signature {
+ Ok(signature.clone())
+ } else {
+ Err(new_binder_exception(
+ ExceptionCode::SERVICE_SPECIFIC,
+ "metadata doesn't contain a signature".to_string(),
+ ))
+ }
} else {
let mut buf = vec![0; MAX_REQUESTING_DATA as usize];
let s = fsverity::read_signature(file.as_raw_fd(), &mut buf).map_err(|e| {
@@ -267,11 +266,12 @@
FdConfig::InputDir(dir) => {
let file = open_readonly_at(dir.as_raw_fd(), &path_buf).map_err(new_errno_error)?;
- // TODO(205987437): Provide the corresponding ".fsv_meta" file when it's created.
- Ok((
- file.as_raw_fd(),
- FdConfig::Readonly { file, alt_merkle_tree: None, alt_signature: None },
- ))
+ let metadata_path_buf = get_fsverity_metadata_path(&path_buf);
+ let metadata = open_readonly_at(dir.as_raw_fd(), &metadata_path_buf)
+ .ok()
+ .and_then(|f| parse_fsverity_metadata(f).ok());
+
+ Ok((file.as_raw_fd(), FdConfig::Readonly { file, alt_metadata: metadata }))
}
FdConfig::OutputDir(_) => {
Err(new_errno_error(Errno::ENOSYS)) // TODO: Implement when needed
diff --git a/authfs/fd_server/src/main.rs b/authfs/fd_server/src/main.rs
index f17b7e8..fe0475f 100644
--- a/authfs/fd_server/src/main.rs
+++ b/authfs/fd_server/src/main.rs
@@ -34,6 +34,7 @@
use std::os::unix::io::FromRawFd;
use aidl::{FdConfig, FdService};
+use authfs_fsverity_metadata::parse_fsverity_metadata;
const RPC_SERVICE_PORT: u32 = 3264; // TODO: support dynamic port for multiple fd_server instances
@@ -54,17 +55,19 @@
fn parse_arg_ro_fds(arg: &str) -> Result<(i32, FdConfig)> {
let result: Result<Vec<i32>, _> = arg.split(':').map(|x| x.parse::<i32>()).collect();
let fds = result?;
- if fds.len() > 3 {
+ if fds.len() > 2 {
bail!("Too many options: {}", arg);
}
Ok((
fds[0],
FdConfig::Readonly {
file: fd_to_file(fds[0])?,
- // Alternative Merkle tree, if provided
- alt_merkle_tree: fds.get(1).map(|fd| fd_to_file(*fd)).transpose()?,
- // Alternative signature, if provided
- alt_signature: fds.get(2).map(|fd| fd_to_file(*fd)).transpose()?,
+ // Alternative metadata source, if provided
+ alt_metadata: fds
+ .get(1)
+ .map(|fd| fd_to_file(*fd))
+ .transpose()?
+ .and_then(|f| parse_fsverity_metadata(f).ok()),
},
))
}