devices: fs: Support FS_IOC_FSGETXATTR

Arcvm needs this ioctl for looking up the project id of an inode.

BUG=b:157189438
TEST=Call the ioctl inside a vm and verify that it succeeds

Change-Id: Ib178cf32b09056f9b1e9acedb49de068d5525a66
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2214964
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Matthias Springer <springerm@chromium.org>
Reviewed-by: Zach Reizner <zachr@chromium.org>
Reviewed-by: Stephen Barber <smbarber@chromium.org>
This commit is contained in:
Chirantan Ekbote 2020-05-25 18:45:33 +09:00 committed by Commit Bot
parent 3f786c1716
commit df71719d7f
4 changed files with 47 additions and 2 deletions

View file

@ -46,6 +46,20 @@ unsafe impl DataInit for fscrypt_policy_v1 {}
ioctl_ior_nr!(FS_IOC_SET_ENCRYPTION_POLICY, 0x66, 19, fscrypt_policy_v1);
ioctl_iow_nr!(FS_IOC_GET_ENCRYPTION_POLICY, 0x66, 21, fscrypt_policy_v1);
#[repr(C)]
#[derive(Clone, Copy)]
struct fsxattr {
_fsx_xflags: u32, /* xflags field value (get/set) */
_fsx_extsize: u32, /* extsize field value (get/set)*/
_fsx_nextents: u32, /* nextents field value (get) */
_fsx_projid: u32, /* project identifier (get/set) */
_fsx_cowextsize: u32, /* CoW extsize field value (get/set)*/
_fsx_pad: [u8; 8],
}
unsafe impl DataInit for fsxattr {}
ioctl_ior_nr!(FS_IOC_FSGETXATTR, 'X' as u32, 31, fsxattr);
type Inode = u64;
type Handle = u64;
@ -727,6 +741,28 @@ impl PassthroughFs {
Ok(IoctlReply::Done(Ok(Vec::new())))
}
}
fn get_fsxattr(&self, handle: Handle) -> io::Result<IoctlReply> {
let data = self
.handles
.lock()
.get(&handle)
.map(Arc::clone)
.ok_or_else(ebadf)?;
let mut buf = MaybeUninit::<fsxattr>::zeroed();
let file = data.file.lock();
// Safe because the kernel will only write to `buf` and we check the return value.
let res = unsafe { ioctl_with_mut_ptr(&*file, FS_IOC_FSGETXATTR(), buf.as_mut_ptr()) };
if res < 0 {
Ok(IoctlReply::Done(Err(io::Error::last_os_error())))
} else {
// Safe because the kernel guarantees that the policy is now initialized.
let xattr = unsafe { buf.assume_init() };
Ok(IoctlReply::Done(Ok(xattr.as_slice().to_vec())))
}
}
}
fn forget_one(
@ -1870,6 +1906,7 @@ impl FileSystem for PassthroughFs {
) -> io::Result<IoctlReply> {
const GET_ENCRYPTION_POLICY: u32 = FS_IOC_GET_ENCRYPTION_POLICY() as u32;
const SET_ENCRYPTION_POLICY: u32 = FS_IOC_SET_ENCRYPTION_POLICY() as u32;
const GET_FSXATTR: u32 = FS_IOC_FSGETXATTR() as u32;
// Normally, we wouldn't need to retry the FS_IOC_GET_ENCRYPTION_POLICY and
// FS_IOC_SET_ENCRYPTION_POLICY ioctls. Unfortunately, the I/O directions for both of them
@ -1899,6 +1936,13 @@ impl FileSystem for PassthroughFs {
self.set_encryption_policy(handle, r)
}
}
GET_FSXATTR => {
if out_size < size_of::<fsxattr>() as u32 {
Err(io::Error::from_raw_os_error(libc::ENOMEM))
} else {
self.get_fsxattr(handle)
}
}
_ => Err(io::Error::from_raw_os_error(libc::ENOTTY)),
}
}

View file

@ -22,6 +22,7 @@ ftruncate: 1
getdents64: 1
getegid: 1
geteuid: 1
ioctl: arg1 == FS_IOC_GET_ENCRYPTION_POLICY || arg1 == FS_IOC_SET_ENCRYPTION_POLICY || arg1 == FS_IOC_FSGETXATTR
linkat: 1
lseek: 1
mkdirat: 1

View file

@ -22,7 +22,7 @@ ftruncate64: 1
getdents64: 1
getegid32: 1
geteuid32: 1
ioctl: arg1 == FS_IOC_GET_ENCRYPTION_POLICY || arg1 == FS_IOC_SET_ENCRYPTION_POLICY
ioctl: arg1 == FS_IOC_GET_ENCRYPTION_POLICY || arg1 == FS_IOC_SET_ENCRYPTION_POLICY || arg1 == FS_IOC_FSGETXATTR
linkat: 1
_llseek: 1
mkdir: 1

View file

@ -21,7 +21,7 @@ ftruncate: 1
getdents64: 1
getegid: 1
geteuid: 1
ioctl: arg1 == FS_IOC_GET_ENCRYPTION_POLICY || arg1 == FS_IOC_SET_ENCRYPTION_POLICY
ioctl: arg1 == FS_IOC_GET_ENCRYPTION_POLICY || arg1 == FS_IOC_SET_ENCRYPTION_POLICY || arg1 == FS_IOC_FSGETXATTR
linkat: 1
lseek: 1
mkdir: 1