devices: fs: Implement FS_IOC_FSSETXATTR

Needed by arcvm.

BUG=b:159297591
TEST=run a test program that calls the ioctl

Change-Id: I1f8c17fa2b2457f5a9e73045c3dbee3440eb943d
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2265932
Auto-Submit: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Tested-by: Chirantan Ekbote <chirantan@chromium.org>
Commit-Queue: Chirantan Ekbote <chirantan@chromium.org>
This commit is contained in:
Chirantan Ekbote 2020-06-25 14:00:42 +09:00 committed by Commit Bot
parent d8447077f0
commit dc82c819f6
4 changed files with 32 additions and 3 deletions

View file

@ -64,6 +64,7 @@ struct fsxattr {
unsafe impl DataInit for fsxattr {}
ioctl_ior_nr!(FS_IOC_FSGETXATTR, 'X' as u32, 31, fsxattr);
ioctl_iow_nr!(FS_IOC_FSSETXATTR, 'X' as u32, 32, fsxattr);
type Inode = u64;
type Handle = u64;
@ -797,6 +798,26 @@ impl PassthroughFs {
Ok(IoctlReply::Done(Ok(xattr.as_slice().to_vec())))
}
}
fn set_fsxattr<R: io::Read>(&self, handle: Handle, r: R) -> io::Result<IoctlReply> {
let data = self
.handles
.lock()
.get(&handle)
.map(Arc::clone)
.ok_or_else(ebadf)?;
let attr = fsxattr::from_reader(r)?;
let file = data.file.lock();
// Safe because this doesn't modify any memory and we check the return value.
let res = unsafe { ioctl_with_ptr(&*file, FS_IOC_FSSETXATTR(), &attr) };
if res < 0 {
Ok(IoctlReply::Done(Err(io::Error::last_os_error())))
} else {
Ok(IoctlReply::Done(Ok(Vec::new())))
}
}
}
fn forget_one(
@ -2011,6 +2032,7 @@ impl FileSystem for PassthroughFs {
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;
const SET_FSXATTR: u32 = FS_IOC_FSSETXATTR() 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
@ -2047,6 +2069,13 @@ impl FileSystem for PassthroughFs {
self.get_fsxattr(handle)
}
}
SET_FSXATTR => {
if in_size < size_of::<fsxattr>() as u32 {
Err(io::Error::from_raw_os_error(libc::EINVAL))
} else {
self.set_fsxattr(handle, r)
}
}
_ => Err(io::Error::from_raw_os_error(libc::ENOTTY)),
}
}

View file

@ -22,7 +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
ioctl: arg1 == FS_IOC_GET_ENCRYPTION_POLICY || arg1 == FS_IOC_SET_ENCRYPTION_POLICY || arg1 == FS_IOC_FSGETXATTR || arg1 == FS_IOC_FSSETXATTR
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 || arg1 == FS_IOC_FSGETXATTR
ioctl: arg1 == FS_IOC_GET_ENCRYPTION_POLICY || arg1 == FS_IOC_SET_ENCRYPTION_POLICY || arg1 == FS_IOC_FSGETXATTR || arg1 == FS_IOC_FSSETXATTR
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 || arg1 == FS_IOC_FSGETXATTR
ioctl: arg1 == FS_IOC_GET_ENCRYPTION_POLICY || arg1 == FS_IOC_SET_ENCRYPTION_POLICY || arg1 == FS_IOC_FSGETXATTR || arg1 == FS_IOC_FSSETXATTR
linkat: 1
lseek: 1
mkdir: 1