mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-25 05:03:05 +00:00
devices: virtio: fs: Support xattr operations for unreadable files
With crrev.com/c/4111635, PassthroughFS specifies O_PATH to open files with no read permission so unreadable (but visible) files are exposed to the guest. However, FUSE's *xattr request such as getxattr for such files weren't supported because f*xattr() won't work for an FD with O_PATH. This CL supports FUSE's getxattr requests for such FDs with O_PATH by calling getxattr() syscall against `self/fd/{FD}` instead of calling fgetxattr() against the FD directly. Also, it supports other similar *xattr requests. As a result, when you run `ls -lZ` in the guest, xattrs are shown properly even for unreadable files. BUG=b:265627547, b:262189957 FIXED=b:265627547 TEST=Run `ls -lZ /var/run/arc/media/removable` on ARCVM and confirm that SELinux attribute `media_rw_data_file` is shown for directories that chronos cannot read. Change-Id: I0afdd088883a1601906646e3aa58de771673a882 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4173359 Reviewed-by: David Stevens <stevensd@chromium.org> Commit-Queue: Keiichi Watanabe <keiichiw@chromium.org>
This commit is contained in:
parent
3eed4ae229
commit
f4dbda24e8
1 changed files with 27 additions and 20 deletions
|
@ -991,11 +991,13 @@ impl PassthroughFs {
|
|||
}
|
||||
|
||||
fn do_getxattr(&self, inode: &InodeData, name: &CStr, value: &mut [u8]) -> io::Result<usize> {
|
||||
let res = if inode.filetype == FileType::Other {
|
||||
// For non-regular files and directories, we cannot open the fd normally. Instead we
|
||||
let file = inode.file.lock();
|
||||
let o_path_file = (file.1 & libc::O_PATH) != 0;
|
||||
let res = if o_path_file {
|
||||
// For FDs opened with `O_PATH`, we cannot call `fgetxattr` normally. Instead we
|
||||
// emulate an _at syscall by changing the CWD to /proc, running the path based syscall,
|
||||
// and then setting the CWD back to the root directory.
|
||||
let path = CString::new(format!("self/fd/{}", inode.as_raw_descriptor()))
|
||||
// and then setting the CWD back to the root directory.
|
||||
let path = CString::new(format!("self/fd/{}", file.0.as_raw_descriptor()))
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
|
||||
// Safe because this will only modify `value` and we check the return value.
|
||||
|
@ -1012,7 +1014,7 @@ impl PassthroughFs {
|
|||
// only write to `value` and we check the return value.
|
||||
unsafe {
|
||||
libc::fgetxattr(
|
||||
inode.as_raw_descriptor(),
|
||||
file.0.as_raw_descriptor(),
|
||||
name.as_ptr(),
|
||||
value.as_mut_ptr() as *mut libc::c_void,
|
||||
value.len() as libc::size_t,
|
||||
|
@ -2242,12 +2244,13 @@ impl FileSystem for PassthroughFs {
|
|||
|
||||
let data = self.find_inode(inode)?;
|
||||
let name = self.rewrite_xattr_name(name);
|
||||
|
||||
if data.filetype == FileType::Other {
|
||||
// For non-regular files and directories, we cannot open the fd normally. Instead we
|
||||
// emulate an _at syscall by changing the CWD to /proc, running the path based syscall,
|
||||
// and then setting the CWD back to the root directory.
|
||||
let path = CString::new(format!("self/fd/{}", data.as_raw_descriptor()))
|
||||
let file = data.file.lock();
|
||||
let o_path_file = (file.1 & libc::O_PATH) != 0;
|
||||
if o_path_file {
|
||||
// For FDs opened with `O_PATH`, we cannot call `fsetxattr` normally. Instead we emulate
|
||||
// an _at syscall by changing the CWD to /proc, running the path based syscall, and then
|
||||
// setting the CWD back to the root directory.
|
||||
let path = CString::new(format!("self/fd/{}", file.0.as_raw_descriptor()))
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
|
||||
// Safe because this doesn't modify any memory and we check the return value.
|
||||
|
@ -2267,7 +2270,7 @@ impl FileSystem for PassthroughFs {
|
|||
// doesn't modify any memory and we check the return value.
|
||||
syscall!(unsafe {
|
||||
libc::fsetxattr(
|
||||
data.as_raw_descriptor(),
|
||||
file.0.as_raw_descriptor(),
|
||||
name.as_ptr(),
|
||||
value.as_ptr() as *const libc::c_void,
|
||||
value.len() as libc::size_t,
|
||||
|
@ -2311,11 +2314,13 @@ impl FileSystem for PassthroughFs {
|
|||
|
||||
let mut buf = vec![0u8; size as usize];
|
||||
|
||||
let res = if data.filetype == FileType::Other {
|
||||
// For non-regular files and directories, we cannot open the fd normally. Instead we
|
||||
let file = data.file.lock();
|
||||
let o_path_file = (file.1 & libc::O_PATH) != 0;
|
||||
let res = if o_path_file {
|
||||
// For FDs opened with `O_PATH`, we cannot call `flistxattr` normally. Instead we
|
||||
// emulate an _at syscall by changing the CWD to /proc, running the path based syscall,
|
||||
// and then setting the CWD back to the root directory.
|
||||
let path = CString::new(format!("self/fd/{}", data.as_raw_descriptor()))
|
||||
let path = CString::new(format!("self/fd/{}", file.0.as_raw_descriptor()))
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
|
||||
// Safe because this will only modify `buf` and we check the return value.
|
||||
|
@ -2331,7 +2336,7 @@ impl FileSystem for PassthroughFs {
|
|||
// write to `buf` and we check the return value.
|
||||
syscall!(unsafe {
|
||||
libc::flistxattr(
|
||||
data.as_raw_descriptor(),
|
||||
file.0.as_raw_descriptor(),
|
||||
buf.as_mut_ptr() as *mut libc::c_char,
|
||||
buf.len() as libc::size_t,
|
||||
)
|
||||
|
@ -2360,11 +2365,13 @@ impl FileSystem for PassthroughFs {
|
|||
let data = self.find_inode(inode)?;
|
||||
let name = self.rewrite_xattr_name(name);
|
||||
|
||||
if data.filetype == FileType::Other {
|
||||
// For non-regular files and directories, we cannot open the fd normally. Instead we
|
||||
let file = data.file.lock();
|
||||
let o_path_file = (file.1 & libc::O_PATH) != 0;
|
||||
if o_path_file {
|
||||
// For files opened with `O_PATH`, we cannot call `fremovexattr` normally. Instead we
|
||||
// emulate an _at syscall by changing the CWD to /proc, running the path based syscall,
|
||||
// and then setting the CWD back to the root directory.
|
||||
let path = CString::new(format!("self/fd/{}", data.as_raw_descriptor()))
|
||||
let path = CString::new(format!("self/fd/{}", file.0.as_raw_descriptor()))
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
||||
|
||||
// Safe because this doesn't modify any memory and we check the return value.
|
||||
|
@ -2374,7 +2381,7 @@ impl FileSystem for PassthroughFs {
|
|||
} else {
|
||||
// For regular files and directories, we can just use fremovexattr. Safe because this
|
||||
// doesn't modify any memory and we check the return value.
|
||||
syscall!(unsafe { libc::fremovexattr(data.as_raw_descriptor(), name.as_ptr()) })?;
|
||||
syscall!(unsafe { libc::fremovexattr(file.0.as_raw_descriptor(), name.as_ptr()) })?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Reference in a new issue