Support setting file mode
File mode of writable AuthFsEntry can now be changed. The mode is
maintain privately in authfs, but also pass through to fd_server.
Note that this change only aims to support getting/setting the file
mode. The mode is not currently used for ACL check.
Bug: 205169366
Test: atest AuthFsHostTest
Test: atest ComposHostTestCases
Test: composd_cmd forced-odrefresh
# exit 80 without ART hack, with permissive SELinux
Change-Id: I2405baedae9ba2be5e84eb84d3228f7be080f8c6
diff --git a/authfs/src/file/dir.rs b/authfs/src/file/dir.rs
index 2a8f359..7f26fd7 100644
--- a/authfs/src/file/dir.rs
+++ b/authfs/src/file/dir.rs
@@ -15,10 +15,12 @@
*/
use log::warn;
+use nix::sys::stat::Mode;
use std::collections::{hash_map, HashMap};
use std::io;
use std::path::{Path, PathBuf};
+use super::attr::Attr;
use super::remote_file::RemoteFileEditor;
use super::{validate_basename, VirtFdService, VirtFdServiceStatus};
use crate::fsverity::VerifiedFileEditor;
@@ -74,37 +76,43 @@
&mut self,
basename: &Path,
inode: Inode,
- ) -> io::Result<VerifiedFileEditor<RemoteFileEditor>> {
- self.validate_argument(basename)?;
-
+ mode: libc::mode_t,
+ ) -> io::Result<(VerifiedFileEditor<RemoteFileEditor>, Attr)> {
+ let mode = self.validate_arguments(basename, mode)?;
let basename_str =
basename.to_str().ok_or_else(|| io::Error::from_raw_os_error(libc::EINVAL))?;
let new_fd = self
.service
- .createFileInDirectory(self.remote_dir_fd, basename_str)
+ .createFileInDirectory(self.remote_dir_fd, basename_str, mode as i32)
.map_err(into_io_error)?;
let new_remote_file =
VerifiedFileEditor::new(RemoteFileEditor::new(self.service.clone(), new_fd));
self.entries.insert(basename.to_path_buf(), DirEntry { inode, is_dir: false });
- Ok(new_remote_file)
+ let new_attr = Attr::new_file_with_mode(self.service.clone(), new_fd, mode);
+ Ok((new_remote_file, new_attr))
}
/// Creates a remote directory named `basename` with corresponding `inode` at the current
/// directory.
- pub fn mkdir(&mut self, basename: &Path, inode: Inode) -> io::Result<RemoteDirEditor> {
- self.validate_argument(basename)?;
-
+ pub fn mkdir(
+ &mut self,
+ basename: &Path,
+ inode: Inode,
+ mode: libc::mode_t,
+ ) -> io::Result<(RemoteDirEditor, Attr)> {
+ let mode = self.validate_arguments(basename, mode)?;
let basename_str =
basename.to_str().ok_or_else(|| io::Error::from_raw_os_error(libc::EINVAL))?;
let new_fd = self
.service
- .createDirectoryInDirectory(self.remote_dir_fd, basename_str)
+ .createDirectoryInDirectory(self.remote_dir_fd, basename_str, mode as i32)
.map_err(into_io_error)?;
let new_remote_dir = RemoteDirEditor::new(self.service.clone(), new_fd);
self.entries.insert(basename.to_path_buf(), DirEntry { inode, is_dir: true });
- Ok(new_remote_dir)
+ let new_attr = Attr::new_dir_with_mode(self.service.clone(), new_fd, mode);
+ Ok((new_remote_dir, new_attr))
}
/// Deletes a file
@@ -167,17 +175,19 @@
}
}
- fn validate_argument(&self, basename: &Path) -> io::Result<()> {
+ fn validate_arguments(&self, basename: &Path, mode: u32) -> io::Result<u32> {
// Kernel should only give us a basename.
debug_assert!(validate_basename(basename).is_ok());
if self.entries.contains_key(basename) {
- Err(io::Error::from_raw_os_error(libc::EEXIST))
- } else if self.entries.len() >= MAX_ENTRIES.into() {
- Err(io::Error::from_raw_os_error(libc::EMLINK))
- } else {
- Ok(())
+ return Err(io::Error::from_raw_os_error(libc::EEXIST));
}
+
+ if self.entries.len() >= MAX_ENTRIES.into() {
+ return Err(io::Error::from_raw_os_error(libc::EMLINK));
+ }
+
+ Ok(Mode::from_bits_truncate(mode).bits())
}
}