authfs: support remote output directory
This change contains 3 major groups:
- authfs/{aidl, fd_server}: new AIDL API and the service implementation
- authfs/src: implement FUSE APIs for creating directory and file, by
interact with the new service API as a client
- authfs/tests, tests/: test coverage
A few notable changes that might help reviewing:
- Now that both AuthFs and FdService struct is no longer immutable (in
order to allow writable directory), their BTreeMap are now guarded by
Arc<Mutex<_>>.
* AuthFs::insert_new_inode and FdService::insert_new_fd are designed
specifically to allow querying then mutating the map, which isn't
trivial.
- File and directory modes from the user program / VFS are currently
ignored (just not to grow the change size).
- Some shuffling of test paths to make it easy to clean up in tearDown.
Bug: 203251769
Test: AuthFsHostTest
Change-Id: I50f3f1ba8a3ebd969cf0f25a8feab2ec8cb1a2dc
diff --git a/authfs/src/main.rs b/authfs/src/main.rs
index a6956e2..0add77f 100644
--- a/authfs/src/main.rs
+++ b/authfs/src/main.rs
@@ -42,7 +42,7 @@
mod fusefs;
use auth::FakeAuthenticator;
-use file::{RemoteFileEditor, RemoteFileReader, RemoteMerkleTreeReader};
+use file::{RemoteDirEditor, RemoteFileEditor, RemoteFileReader, RemoteMerkleTreeReader};
use fsverity::{VerifiedFileEditor, VerifiedFileReader};
use fusefs::{FileConfig, Inode};
@@ -81,6 +81,15 @@
#[structopt(long, parse(try_from_str = parse_remote_new_rw_file_option))]
remote_new_rw_file: Vec<OptionRemoteRwFile>,
+ /// A new directory that is assumed empty in the backing filesystem. New files created in this
+ /// directory are integrity-protected in the same way as --remote-new-verified-file. Can be
+ /// multiple.
+ ///
+ /// For example, `--remote-new-verified-dir 12:34` tells the filesystem to associate entry 12
+ /// with a remote dir FD 34.
+ #[structopt(long, parse(try_from_str = parse_remote_new_rw_dir_option))]
+ remote_new_rw_dir: Vec<OptionRemoteRwDir>,
+
/// Enable debugging features.
#[structopt(long)]
debug: bool,
@@ -111,6 +120,13 @@
remote_id: i32,
}
+struct OptionRemoteRwDir {
+ ino: Inode,
+
+ /// ID to refer to the remote dir.
+ remote_id: i32,
+}
+
fn parse_remote_ro_file_option(option: &str) -> Result<OptionRemoteRoFile> {
let strs: Vec<&str> = option.split(':').collect();
if strs.len() != 3 {
@@ -145,6 +161,17 @@
})
}
+fn parse_remote_new_rw_dir_option(option: &str) -> Result<OptionRemoteRwDir> {
+ let strs: Vec<&str> = option.split(':').collect();
+ if strs.len() != 2 {
+ bail!("Invalid option: {}", option);
+ }
+ Ok(OptionRemoteRwDir {
+ ino: strs[0].parse::<Inode>().unwrap(),
+ remote_id: strs[1].parse::<i32>().unwrap(),
+ })
+}
+
fn new_config_remote_verified_file(
service: file::VirtFdService,
remote_id: i32,
@@ -182,6 +209,14 @@
Ok(FileConfig::VerifiedNew { editor: VerifiedFileEditor::new(remote_file) })
}
+fn new_config_remote_new_verified_dir(
+ service: file::VirtFdService,
+ remote_id: i32,
+) -> Result<FileConfig> {
+ let dir = RemoteDirEditor::new(service, remote_id);
+ Ok(FileConfig::VerifiedNewDirectory { dir })
+}
+
fn prepare_file_pool(args: &Args) -> Result<BTreeMap<Inode, FileConfig>> {
let mut file_pool = BTreeMap::new();
@@ -216,6 +251,13 @@
);
}
+ for config in &args.remote_new_rw_dir {
+ file_pool.insert(
+ config.ino,
+ new_config_remote_new_verified_dir(service.clone(), config.remote_id)?,
+ );
+ }
+
Ok(file_pool)
}