authfs: Support binder-backed file source
This change adds remote file support to authfs. This allows a process to
read a remote file through a local path with transparent fs-verity
verification.
This is supposed to work across VM boundary, but before the remote
binder is ready, this change uses local binder.
Test: Shell #1
$ adb shell 'exec
9</system/bin/sh
8</data/local/tmp/input.4m
7</data/local/tmp/input.4m.merkle_dump
6</data/local/tmp/input.4m.fsv_sig
fd_server
--ro-fds 9
--ro-fds 8:7:6'`
Shell #2
$ adb push tools/device-test.sh /data/local/tmp/ && \
adb shell /data/local/tmp/device-test.sh
Change-Id: Ia69fae548b83ff3ba572f4a496a7cbcca518cbef
diff --git a/authfs/src/fusefs.rs b/authfs/src/fusefs.rs
index 484aad4..0dfd0af 100644
--- a/authfs/src/fusefs.rs
+++ b/authfs/src/fusefs.rs
@@ -32,6 +32,7 @@
use crate::common::{divide_roundup, COMMON_PAGE_SIZE};
use crate::fsverity::FsverityChunkedFileReader;
use crate::reader::{ChunkedFileReader, ReadOnlyDataByChunk};
+use crate::remote_file::{RemoteChunkedFileReader, RemoteFsverityMerkleTreeReader};
// We're reading the backing file by chunk, so setting the block size to be the same.
const BLOCK_SIZE: usize = COMMON_PAGE_SIZE as usize;
@@ -41,6 +42,9 @@
pub type Inode = u64;
type Handle = u64;
+type RemoteFsverityChunkedFileReader =
+ FsverityChunkedFileReader<RemoteChunkedFileReader, RemoteFsverityMerkleTreeReader>;
+
// A debug only type where everything are stored as local files.
type FileBackedFsverityChunkedFileReader =
FsverityChunkedFileReader<ChunkedFileReader, ChunkedFileReader>;
@@ -48,6 +52,8 @@
pub enum FileConfig {
LocalVerifiedFile(FileBackedFsverityChunkedFileReader, u64),
LocalUnverifiedFile(ChunkedFileReader, u64),
+ RemoteVerifiedFile(RemoteFsverityChunkedFileReader, u64),
+ RemoteUnverifiedFile(RemoteChunkedFileReader, u64),
}
struct AuthFs {
@@ -204,7 +210,9 @@
let inode = num.parse::<Inode>().map_err(|_| io::Error::from_raw_os_error(libc::ENOENT))?;
let st = match self.get_file_config(&inode)? {
FileConfig::LocalVerifiedFile(_, file_size)
- | FileConfig::LocalUnverifiedFile(_, file_size) => create_stat(inode, *file_size)?,
+ | FileConfig::LocalUnverifiedFile(_, file_size)
+ | FileConfig::RemoteUnverifiedFile(_, file_size)
+ | FileConfig::RemoteVerifiedFile(_, file_size) => create_stat(inode, *file_size)?,
};
Ok(Entry {
inode,
@@ -224,7 +232,9 @@
Ok((
match self.get_file_config(&inode)? {
FileConfig::LocalVerifiedFile(_, file_size)
- | FileConfig::LocalUnverifiedFile(_, file_size) => create_stat(inode, *file_size)?,
+ | FileConfig::LocalUnverifiedFile(_, file_size)
+ | FileConfig::RemoteUnverifiedFile(_, file_size)
+ | FileConfig::RemoteVerifiedFile(_, file_size) => create_stat(inode, *file_size)?,
},
DEFAULT_METADATA_TIMEOUT,
))
@@ -239,13 +249,13 @@
// Since file handle is not really used in later operations (which use Inode directly),
// return None as the handle..
match self.get_file_config(&inode)? {
- FileConfig::LocalVerifiedFile(_, _) => {
+ FileConfig::LocalVerifiedFile(_, _) | FileConfig::RemoteVerifiedFile(_, _) => {
check_access_mode(flags, libc::O_RDONLY)?;
// Once verified, and only if verified, the file content can be cached. This is not
// really needed for a local file, but is the behavior of RemoteVerifiedFile later.
Ok((None, fuse::sys::OpenOptions::KEEP_CACHE))
}
- FileConfig::LocalUnverifiedFile(_, _) => {
+ FileConfig::LocalUnverifiedFile(_, _) | FileConfig::RemoteUnverifiedFile(_, _) => {
check_access_mode(flags, libc::O_RDONLY)?;
// Do not cache the content. This type of file is supposed to be verified using
// dm-verity. The filesystem mount over dm-verity already is already cached, so use
@@ -273,6 +283,12 @@
FileConfig::LocalUnverifiedFile(file, file_size) => {
read_chunks(w, file, *file_size, offset, size)
}
+ FileConfig::RemoteVerifiedFile(file, file_size) => {
+ read_chunks(w, file, *file_size, offset, size)
+ }
+ FileConfig::RemoteUnverifiedFile(file, file_size) => {
+ read_chunks(w, file, *file_size, offset, size)
+ }
}
}
}