fd_server: support open file by path at a dir fd
When fd_server allows the client/authfs to (only) read a directory, authfs
will be able to serve the shared directory remotely (and implement its own
authentication).
Bug: 203251769
Test: atest AuthFsHostTest
Change-Id: If7209ec496b305ba8f469a382c2f775dcd0d1711
diff --git a/authfs/fd_server/src/aidl.rs b/authfs/fd_server/src/aidl.rs
index 0c41eac..fa1914a 100644
--- a/authfs/fd_server/src/aidl.rs
+++ b/authfs/fd_server/src/aidl.rs
@@ -25,8 +25,8 @@
use std::fs::File;
use std::io;
use std::os::unix::fs::FileExt;
-use std::os::unix::io::{AsRawFd, FromRawFd};
-use std::path::MAIN_SEPARATOR;
+use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
+use std::path::{Component, Path, PathBuf, MAIN_SEPARATOR};
use std::sync::{Arc, Mutex};
use crate::fsverity;
@@ -59,9 +59,11 @@
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>,
},
@@ -69,6 +71,9 @@
/// regular file and does not have any specific property.
ReadWrite(File),
+ /// A read-only directory to serve by this server.
+ InputDir(Dir),
+
/// A writable directory to serve by this server.
OutputDir(Dir),
}
@@ -132,7 +137,7 @@
new_errno_error(Errno::EIO)
})
}
- FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
+ FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
})
}
@@ -165,7 +170,7 @@
// use.
Err(new_errno_error(Errno::ENOSYS))
}
- FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
+ FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
})
}
@@ -195,7 +200,7 @@
// There is no signature for a writable file.
Err(new_errno_error(Errno::ENOSYS))
}
- FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
+ FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
})
}
@@ -213,7 +218,7 @@
new_errno_error(Errno::EIO)
})? as i32)
}
- FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
+ FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
})
}
@@ -229,7 +234,7 @@
new_errno_error(Errno::EIO)
})
}
- FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
+ FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
})
}
@@ -254,7 +259,31 @@
// for a writable file.
Err(new_errno_error(Errno::ENOSYS))
}
- FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
+ FdConfig::InputDir(_) | FdConfig::OutputDir(_) => Err(new_errno_error(Errno::EISDIR)),
+ })
+ }
+
+ fn openFileInDirectory(&self, fd: i32, file_path: &str) -> BinderResult<i32> {
+ let path_buf = PathBuf::from(file_path);
+ // Checks if the path is a simple, related path.
+ if path_buf.components().any(|c| !matches!(c, Component::Normal(_))) {
+ return Err(new_errno_error(Errno::EINVAL));
+ }
+
+ self.insert_new_fd(fd, |config| match config {
+ 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 },
+ ))
+ }
+ FdConfig::OutputDir(_) => {
+ Err(new_errno_error(Errno::ENOSYS)) // TODO: Implement when needed
+ }
+ _ => Err(new_errno_error(Errno::ENOTDIR)),
})
}
@@ -263,6 +292,7 @@
return Err(new_errno_error(Errno::EINVAL));
}
self.insert_new_fd(fd, |config| match config {
+ FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
FdConfig::OutputDir(dir) => {
let new_fd = openat(
dir.as_raw_fd(),
@@ -286,6 +316,7 @@
return Err(new_errno_error(Errno::EINVAL));
}
self.insert_new_fd(dir_fd, |config| match config {
+ FdConfig::InputDir(_) => Err(new_errno_error(Errno::EACCES)),
FdConfig::OutputDir(_) => {
mkdirat(dir_fd, basename, Mode::S_IRWXU).map_err(new_errno_error)?;
let new_dir = Dir::openat(
@@ -313,3 +344,10 @@
fn new_errno_error(errno: Errno) -> Status {
new_binder_service_specific_error(errno as i32, errno.desc())
}
+
+fn open_readonly_at(dir_fd: RawFd, path: &Path) -> nix::Result<File> {
+ let new_fd = openat(dir_fd, path, OFlag::O_RDONLY, Mode::empty())?;
+ // SAFETY: new_fd is just created successfully and not owned.
+ let new_file = unsafe { File::from_raw_fd(new_fd) };
+ Ok(new_file)
+}