tree-wide: replace data_model::zerocopy_from_*()

Use zerocopy functions directly instead. This is a step toward replacing
our data_model crate with standard crates.io functionality where
possible.

BUG=b:312312646
TEST=tools/dev_container tools/presubmit

Change-Id: I9717edce6fe2b4ca53ad9043db61de2e9bc55b78
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/5046345
Reviewed-by: Dennis Kempin <denniskempin@google.com>
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: Noah Gold <nkgold@google.com>
This commit is contained in:
Daniel Verkamp 2023-11-20 19:14:10 -08:00 committed by crosvm LUCI
parent 5fe672aaf4
commit 742791deef
13 changed files with 131 additions and 138 deletions

4
Cargo.lock generated
View file

@ -739,7 +739,6 @@ dependencies = [
"crosvm_cli",
"crosvm_plugin",
"ctrlc",
"data_model",
"devices",
"disk",
"document-features",
@ -1186,7 +1185,6 @@ dependencies = [
"bitflags 2.4.0",
"cros_tracing",
"crossbeam-utils",
"data_model",
"enumn",
"libc",
"remain",
@ -1335,7 +1333,6 @@ dependencies = [
"cc",
"cfg-if",
"cros_tracing",
"data_model",
"euclid",
"libc",
"linux_input_sys",
@ -2970,7 +2967,6 @@ dependencies = [
"base",
"bitflags 2.4.0",
"cfg-if",
"data_model",
"enumn",
"libc",
"remain",

View file

@ -411,7 +411,6 @@ cros_async = { path = "cros_async" }
cros_tracing = { path = "cros_tracing" }
crosvm_cli = { path = "crosvm_cli" }
crosvm_plugin = { path = "crosvm_plugin", optional = true }
data_model = { path ="common/data_model" }
devices = { path = "devices" }
disk = { path = "disk" }
document-features = { version = "0.2", optional = true }

View file

@ -2,31 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::io;
use zerocopy::AsBytes;
use zerocopy::FromBytes;
use zerocopy::FromZeroes;
use zerocopy::Ref;
pub fn zerocopy_from_reader<R: io::Read, T: AsBytes + FromBytes + FromZeroes>(
mut read: R,
) -> io::Result<T> {
let mut out = T::new_zeroed();
read.read_exact(out.as_bytes_mut())?;
Ok(out)
}
pub fn zerocopy_from_mut_slice<T: FromBytes + AsBytes>(data: &mut [u8]) -> Option<&mut T> {
let lv: Ref<&mut [u8], T> = Ref::new(data)?;
Some(lv.into_mut())
}
pub fn zerocopy_from_slice<T: FromBytes>(data: &[u8]) -> Option<&T> {
let lv: Ref<&[u8], T> = Ref::new(data)?;
Some(lv.into_ref())
}
pub mod endian;
pub use crate::endian::*;

View file

@ -39,7 +39,6 @@ use base::AsRawDescriptor;
use base::FromRawDescriptor;
use base::Protection;
use base::RawDescriptor;
use data_model::zerocopy_from_reader;
use fuse::filesystem::Context;
use fuse::filesystem::DirectoryIterator;
use fuse::filesystem::Entry;
@ -1308,7 +1307,7 @@ impl PassthroughFs {
#[cfg_attr(not(feature = "arc_quota"), allow(unused_variables))] ctx: Context,
inode: Inode,
handle: Handle,
r: R,
mut r: R,
) -> io::Result<IoctlReply> {
let data: Arc<dyn AsRawDescriptor> = if self.zero_message_open.load(Ordering::Relaxed) {
self.find_inode(inode)?
@ -1316,7 +1315,8 @@ impl PassthroughFs {
self.find_handle(handle, inode)?
};
let in_attr: fsxattr = zerocopy_from_reader(r)?;
let mut in_attr = fsxattr::new_zeroed();
r.read_exact(in_attr.as_bytes_mut())?;
#[cfg(feature = "arc_quota")]
let st = stat(&*data)?;
@ -1399,7 +1399,7 @@ impl PassthroughFs {
#[cfg_attr(not(feature = "arc_quota"), allow(unused_variables))] ctx: Context,
inode: Inode,
handle: Handle,
r: R,
mut r: R,
) -> io::Result<IoctlReply> {
let data: Arc<dyn AsRawDescriptor> = if self.zero_message_open.load(Ordering::Relaxed) {
self.find_inode(inode)?
@ -1408,7 +1408,8 @@ impl PassthroughFs {
};
// The ioctl encoding is a long but the parameter is actually an int.
let in_flags: c_int = zerocopy_from_reader(r)?;
let mut in_flags: c_int = 0;
r.read_exact(in_flags.as_bytes_mut())?;
#[cfg(feature = "arc_quota")]
let st = stat(&*data)?;
@ -1522,7 +1523,8 @@ impl PassthroughFs {
data
};
let mut arg: fsverity_enable_arg = zerocopy_from_reader(&mut r)?;
let mut arg = fsverity_enable_arg::new_zeroed();
r.read_exact(arg.as_bytes_mut())?;
let mut salt;
if arg.salt_size > 0 {
@ -1565,7 +1567,7 @@ impl PassthroughFs {
&self,
inode: Inode,
handle: Handle,
r: R,
mut r: R,
out_size: u32,
) -> io::Result<IoctlReply> {
let data: Arc<dyn AsRawDescriptor> = if self.zero_message_open.load(Ordering::Relaxed) {
@ -1574,7 +1576,8 @@ impl PassthroughFs {
self.find_handle(handle, inode)?
};
let digest: fsverity_digest = zerocopy_from_reader(r)?;
let mut digest = fsverity_digest::new_zeroed();
r.read_exact(digest.as_bytes_mut())?;
// Taken from fs/verity/fsverity_private.h.
const FS_VERITY_MAX_DIGEST_SIZE: u16 = 64;

View file

@ -24,7 +24,6 @@ use base::VolatileSlice;
use cros_async::BackingMemory;
use cros_async::Executor;
use cros_async::IoSource;
use data_model::zerocopy_from_reader;
use data_model::Le16;
use data_model::Le32;
use remain::sorted;
@ -111,13 +110,15 @@ pub struct AndroidSparse {
chunks: BTreeMap<u64, ChunkWithSize>,
}
fn parse_chunk<T: Read + Seek>(mut input: &mut T, blk_sz: u64) -> Result<Option<ChunkWithSize>> {
fn parse_chunk<T: Read + Seek>(input: &mut T, blk_sz: u64) -> Result<Option<ChunkWithSize>> {
const HEADER_SIZE: usize = mem::size_of::<ChunkHeader>();
let current_offset = input
.stream_position()
.map_err(Error::ReadSpecificationError)?;
let chunk_header: ChunkHeader =
zerocopy_from_reader(&mut input).map_err(Error::ReadSpecificationError)?;
let mut chunk_header = ChunkHeader::new_zeroed();
input
.read_exact(chunk_header.as_bytes_mut())
.map_err(Error::ReadSpecificationError)?;
let chunk_body_size = (chunk_header.total_sz.to_native() as usize)
.checked_sub(HEADER_SIZE)
.ok_or(Error::InvalidSpecification(format!(
@ -166,8 +167,9 @@ impl AndroidSparse {
pub fn from_file(mut file: File) -> Result<AndroidSparse> {
file.seek(SeekFrom::Start(0))
.map_err(Error::ReadSpecificationError)?;
let sparse_header: SparseHeader =
zerocopy_from_reader(&mut file).map_err(Error::ReadSpecificationError)?;
let mut sparse_header = SparseHeader::new_zeroed();
file.read_exact(sparse_header.as_bytes_mut())
.map_err(Error::ReadSpecificationError)?;
if sparse_header.magic != SPARSE_HEADER_MAGIC {
return Err(Error::InvalidSpecification(format!(
"Header did not match magic constant. Expected {:x}, was {:x}",

View file

@ -12,7 +12,6 @@ base = "*"
bitflags = "2.2.1"
crossbeam-utils = "0.8"
cros_tracing = { path = "../cros_tracing" }
data_model = { path = "../common/data_model" }
enumn = "0.1.0"
libc = { version = "*", features = ["extra_traits"] }
remain = "0.2"

View file

@ -15,10 +15,9 @@ use std::time::Duration;
use base::error;
use base::pagesize;
use base::Protection;
use data_model::zerocopy_from_reader;
use data_model::zerocopy_from_slice;
use zerocopy::AsBytes;
use zerocopy::Unalign;
use zerocopy::FromBytes;
use zerocopy::FromZeroes;
use crate::filesystem::Context;
use crate::filesystem::DirEntry;
@ -39,7 +38,14 @@ const DIRENT_PADDING: [u8; 8] = [0; 8];
const SELINUX_XATTR_CSTR: &[u8] = b"security.selinux\0";
/// A trait for reading from the underlying FUSE endpoint.
pub trait Reader: io::Read {}
pub trait Reader: io::Read {
fn read_struct<T: AsBytes + FromBytes + FromZeroes>(&mut self) -> Result<T> {
let mut out = T::new_zeroed();
self.read_exact(out.as_bytes_mut())
.map_err(Error::DecodeMessage)?;
Ok(out)
}
}
impl<R: Reader> Reader for &'_ mut R {}
@ -152,7 +158,7 @@ impl<F: FileSystem + Sync> Server<F> {
w: W,
mapper: M,
) -> Result<usize> {
let in_header: InHeader = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let in_header: InHeader = r.read_struct()?;
cros_tracing::trace_simple_print!("fuse server: handle_message: in_header={:?}", in_header);
if in_header.len
@ -247,7 +253,7 @@ impl<F: FileSystem + Sync> Server<F> {
}
fn forget<R: Reader>(&self, in_header: InHeader, mut r: R) -> Result<usize> {
let ForgetIn { nlookup } = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let ForgetIn { nlookup } = r.read_struct()?;
self.fs
.forget(Context::from(in_header), in_header.nodeid.into(), nlookup);
@ -261,7 +267,7 @@ impl<F: FileSystem + Sync> Server<F> {
flags,
dummy: _,
fh,
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
let handle = if (flags & GETATTR_FH) != 0 {
Some(fh.into())
@ -287,7 +293,7 @@ impl<F: FileSystem + Sync> Server<F> {
}
fn setattr<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let setattr_in: SetattrIn = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let setattr_in: SetattrIn = r.read_struct()?;
let handle = if setattr_in.valid & FATTR_FH != 0 {
Some(setattr_in.fh.into())
@ -374,7 +380,7 @@ impl<F: FileSystem + Sync> Server<F> {
fn mknod<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let MknodIn {
mode, rdev, umask, ..
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
let buflen = (in_header.len as usize)
.checked_sub(size_of::<InHeader>())
@ -412,7 +418,7 @@ impl<F: FileSystem + Sync> Server<F> {
}
fn mkdir<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let MkdirIn { mode, umask } = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let MkdirIn { mode, umask } = r.read_struct()?;
let buflen = (in_header.len as usize)
.checked_sub(size_of::<InHeader>())
@ -454,8 +460,7 @@ impl<F: FileSystem + Sync> Server<F> {
mut r: R,
w: W,
) -> Result<usize> {
let ChromeOsTmpfileIn { mode, umask } =
zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let ChromeOsTmpfileIn { mode, umask } = r.read_struct()?;
let len = (in_header.len as usize)
.checked_sub(size_of::<InHeader>())
@ -559,14 +564,13 @@ impl<F: FileSystem + Sync> Server<F> {
}
fn rename<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let RenameIn { newdir } = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let RenameIn { newdir } = r.read_struct()?;
self.do_rename(in_header, size_of::<RenameIn>(), newdir, 0, r, w)
}
fn rename2<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let Rename2In { newdir, flags, .. } =
zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let Rename2In { newdir, flags, .. } = r.read_struct()?;
#[allow(clippy::unnecessary_cast)]
let flags = flags & (libc::RENAME_EXCHANGE | libc::RENAME_NOREPLACE) as u32;
@ -575,7 +579,7 @@ impl<F: FileSystem + Sync> Server<F> {
}
fn link<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let LinkIn { oldnodeid } = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let LinkIn { oldnodeid } = r.read_struct()?;
let namelen = (in_header.len as usize)
.checked_sub(size_of::<InHeader>())
@ -601,7 +605,7 @@ impl<F: FileSystem + Sync> Server<F> {
}
fn open<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let OpenIn { flags, .. } = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let OpenIn { flags, .. } = r.read_struct()?;
match self
.fs
@ -634,7 +638,7 @@ impl<F: FileSystem + Sync> Server<F> {
lock_owner,
flags,
..
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
if size > self.fs.max_buffer_size() {
return reply_error(
@ -694,7 +698,7 @@ impl<F: FileSystem + Sync> Server<F> {
lock_owner,
flags,
..
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
if size > self.fs.max_buffer_size() {
return reply_error(
@ -751,7 +755,7 @@ impl<F: FileSystem + Sync> Server<F> {
flags,
release_flags,
lock_owner,
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
let flush = release_flags & RELEASE_FLUSH != 0;
let flock_release = release_flags & RELEASE_FLOCK_UNLOCK != 0;
@ -778,7 +782,7 @@ impl<F: FileSystem + Sync> Server<F> {
fn fsync<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let FsyncIn {
fh, fsync_flags, ..
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
let datasync = fsync_flags & 0x1 != 0;
match self.fs.fsync(
@ -793,8 +797,7 @@ impl<F: FileSystem + Sync> Server<F> {
}
fn setxattr<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let SetxattrIn { size, flags } =
zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let SetxattrIn { size, flags } = r.read_struct()?;
// The name and value and encoded one after another and separated by a '\0' character.
let len = (in_header.len as usize)
@ -831,7 +834,7 @@ impl<F: FileSystem + Sync> Server<F> {
}
fn getxattr<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let GetxattrIn { size, .. } = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let GetxattrIn { size, .. } = r.read_struct()?;
let namelen = (in_header.len as usize)
.checked_sub(size_of::<InHeader>())
@ -874,7 +877,7 @@ impl<F: FileSystem + Sync> Server<F> {
mut r: R,
w: W,
) -> Result<usize> {
let GetxattrIn { size, .. } = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let GetxattrIn { size, .. } = r.read_struct()?;
if size > self.fs.max_buffer_size() {
return reply_error(
@ -932,7 +935,7 @@ impl<F: FileSystem + Sync> Server<F> {
unused: _,
padding: _,
lock_owner,
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
match self.fs.flush(
Context::from(in_header),
@ -952,7 +955,7 @@ impl<F: FileSystem + Sync> Server<F> {
minor,
max_readahead,
flags,
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
if major < KERNEL_VERSION {
error!("Unsupported fuse protocol version: {}.{}", major, minor);
@ -990,7 +993,7 @@ impl<F: FileSystem + Sync> Server<F> {
if (FsOptions::from_bits_truncate(u64::from(flags)) & FsOptions::INIT_EXT).is_empty() {
InitInExt::default()
} else {
zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?
r.read_struct()?
};
// These fuse features are supported by this server by default.
@ -1052,7 +1055,7 @@ impl<F: FileSystem + Sync> Server<F> {
}
fn opendir<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let OpenIn { flags, .. } = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let OpenIn { flags, .. } = r.read_struct()?;
match self
.fs
@ -1079,7 +1082,7 @@ impl<F: FileSystem + Sync> Server<F> {
) -> Result<usize> {
let ReadIn {
fh, offset, size, ..
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
if size > self.fs.max_buffer_size() {
return reply_error(
@ -1171,7 +1174,7 @@ impl<F: FileSystem + Sync> Server<F> {
cros_tracing::trace_simple_print!("fuse server: readdirplus: in_header={:?}", in_header);
let ReadIn {
fh, offset, size, ..
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
if size > self.fs.max_buffer_size() {
return reply_error(
@ -1258,8 +1261,7 @@ impl<F: FileSystem + Sync> Server<F> {
mut r: R,
w: W,
) -> Result<usize> {
let ReleaseIn { fh, flags, .. } =
zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let ReleaseIn { fh, flags, .. } = r.read_struct()?;
match self.fs.releasedir(
Context::from(in_header),
@ -1275,7 +1277,7 @@ impl<F: FileSystem + Sync> Server<F> {
fn fsyncdir<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let FsyncIn {
fh, fsync_flags, ..
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
let datasync = fsync_flags & 0x1 != 0;
match self.fs.fsyncdir(
@ -1314,7 +1316,7 @@ impl<F: FileSystem + Sync> Server<F> {
}
fn access<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let AccessIn { mask, .. } = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let AccessIn { mask, .. } = r.read_struct()?;
match self
.fs
@ -1328,7 +1330,7 @@ impl<F: FileSystem + Sync> Server<F> {
fn create<R: Reader, W: Writer>(&self, in_header: InHeader, mut r: R, w: W) -> Result<usize> {
let CreateIn {
flags, mode, umask, ..
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
let buflen = (in_header.len as usize)
.checked_sub(size_of::<InHeader>())
@ -1414,7 +1416,7 @@ impl<F: FileSystem + Sync> Server<F> {
arg,
in_size,
out_size,
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
let res = self.fs.ioctl(
in_header.into(),
@ -1466,8 +1468,7 @@ impl<F: FileSystem + Sync> Server<F> {
mut r: R,
w: W,
) -> Result<usize> {
let BatchForgetIn { count, .. } =
zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let BatchForgetIn { count, .. } = r.read_struct()?;
if let Some(size) = (count as usize).checked_mul(size_of::<ForgetOne>()) {
if size > self.fs.max_buffer_size() as usize {
@ -1487,11 +1488,8 @@ impl<F: FileSystem + Sync> Server<F> {
let mut requests = Vec::with_capacity(count as usize);
for _ in 0..count {
requests.push(
zerocopy_from_reader(&mut r)
.map(|f: ForgetOne| (f.nodeid.into(), f.nlookup))
.map_err(Error::DecodeMessage)?,
);
let f: ForgetOne = r.read_struct()?;
requests.push((f.nodeid.into(), f.nlookup));
}
self.fs.batch_forget(Context::from(in_header), requests);
@ -1512,7 +1510,7 @@ impl<F: FileSystem + Sync> Server<F> {
length,
mode,
..
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
match self.fs.fallocate(
Context::from(in_header),
@ -1549,7 +1547,7 @@ impl<F: FileSystem + Sync> Server<F> {
off_dst,
len,
flags,
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
match self.fs.copy_file_range(
Context::from(in_header),
@ -1592,7 +1590,7 @@ impl<F: FileSystem + Sync> Server<F> {
len,
flags,
moffset,
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
let flags = SetUpMappingFlags::from_bits_truncate(flags);
let mut prot = 0;
@ -1643,8 +1641,7 @@ impl<F: FileSystem + Sync> Server<F> {
W: Writer,
M: Mapper,
{
let RemoveMappingIn { count } =
zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
let RemoveMappingIn { count } = r.read_struct()?;
// `FUSE_REMOVEMAPPING_MAX_ENTRY` is defined as
// `PAGE_SIZE / sizeof(struct fuse_removemapping_one)` in /kernel/include/uapi/linux/fuse.h.
@ -1660,7 +1657,8 @@ impl<F: FileSystem + Sync> Server<F> {
let mut msgs = Vec::with_capacity(count as usize);
for _ in 0..(count as usize) {
msgs.push(zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?);
let msg: RemoveMappingOne = r.read_struct()?;
msgs.push(msg);
}
match self.fs.remove_mapping(&msgs, mapper) {
@ -1677,7 +1675,7 @@ impl<F: FileSystem + Sync> Server<F> {
) -> Result<usize> {
let CreateIn {
flags, mode, umask, ..
} = zerocopy_from_reader(&mut r).map_err(Error::DecodeMessage)?;
} = r.read_struct()?;
let buflen = (in_header.len as usize)
.checked_sub(size_of::<InHeader>())
@ -1963,34 +1961,32 @@ fn parse_selinux_xattr(buf: &[u8]) -> Result<Option<&CStr>> {
// Because the security context data block may have been preceded by variable-length strings,
// `SecctxHeader` and the subsequent `Secctx` structs may not be correctly byte-aligned
// within `buf`.
let secctx_header: &Unalign<SecctxHeader> =
zerocopy_from_slice(&buf[0..size_of::<SecctxHeader>()]).ok_or(Error::DecodeMessage(
io::Error::from_raw_os_error(libc::EINVAL),
))?;
let secctx_header = SecctxHeader::read_from_prefix(buf).ok_or(Error::DecodeMessage(
io::Error::from_raw_os_error(libc::EINVAL),
))?;
// FUSE 7.38 introduced a generic request extension with the same structure as `SecctxHeader`.
// A `nr_secctx` value above `MAX_NR_SECCTX` indicates that this data block does not contain
// any security context information.
if secctx_header.get().nr_secctx > MAX_NR_SECCTX {
if secctx_header.nr_secctx > MAX_NR_SECCTX {
return Ok(None);
}
let mut cur_secctx_pos = size_of::<SecctxHeader>();
for _ in 0..secctx_header.get().nr_secctx {
for _ in 0..secctx_header.nr_secctx {
// `SecctxHeader.size` denotes the total size for the `SecctxHeader`, each of the
// `nr_secctx` `Secctx` structs along with the corresponding context name and value,
// and any additional padding.
if (cur_secctx_pos + size_of::<Secctx>()) > buf.len()
|| (cur_secctx_pos + size_of::<Secctx>()) > secctx_header.get().size as usize
|| (cur_secctx_pos + size_of::<Secctx>()) > secctx_header.size as usize
{
return Err(Error::InvalidHeaderLength);
}
let secctx: &Unalign<Secctx> =
zerocopy_from_slice(&buf[cur_secctx_pos..(cur_secctx_pos + size_of::<Secctx>())])
.ok_or(Error::DecodeMessage(io::Error::from_raw_os_error(
libc::EINVAL,
)))?;
let secctx =
Secctx::read_from(&buf[cur_secctx_pos..(cur_secctx_pos + size_of::<Secctx>())]).ok_or(
Error::DecodeMessage(io::Error::from_raw_os_error(libc::EINVAL)),
)?;
cur_secctx_pos += size_of::<Secctx>();
@ -2008,13 +2004,13 @@ fn parse_selinux_xattr(buf: &[u8]) -> Result<Option<&CStr>> {
let value = secctx_data[1];
cur_secctx_pos += name.to_bytes_with_nul().len() + value.to_bytes_with_nul().len();
if cur_secctx_pos > secctx_header.get().size as usize {
if cur_secctx_pos > secctx_header.size as usize {
return Err(Error::InvalidHeaderLength);
}
// `Secctx.size` contains the size of the security context value (not including the
// corresponding context name).
if value.to_bytes_with_nul().len() as u32 != secctx.get().size {
if value.to_bytes_with_nul().len() as u32 != secctx.size {
return Err(Error::InvalidHeaderLength);
}
@ -2030,7 +2026,7 @@ fn parse_selinux_xattr(buf: &[u8]) -> Result<Option<&CStr>> {
.checked_add(7)
.map(|l| l & !7)
.ok_or_else(|| Error::InvalidHeaderLength)?;
if padded_secctx_size != secctx_header.get().size as usize {
if padded_secctx_size != secctx_header.size as usize {
return Err(Error::InvalidHeaderLength);
}

View file

@ -11,7 +11,6 @@ vulkan_display = [ "vulkano", "ash", "rand", "protos", "protobuf", "euclid", "sm
[dependencies]
anyhow = "*"
data_model = { path = "../common/data_model" }
libc = "*"
base = { path = "../base" }
linux_input_sys = { path = "../linux_input_sys" }

View file

@ -5,6 +5,7 @@
use std::collections::VecDeque;
use std::fmt;
use std::io;
use std::io::Read;
use std::io::Write;
use std::iter::ExactSizeIterator;
@ -12,12 +13,12 @@ use base::AsRawDescriptor;
use base::RawDescriptor;
use base::ReadNotifier;
use base::StreamChannel;
use data_model::zerocopy_from_reader;
use linux_input_sys::virtio_input_event;
use linux_input_sys::InputEventDecoder;
use serde::Deserialize;
use serde::Serialize;
use zerocopy::AsBytes;
use zerocopy::FromZeroes;
const EVENT_SIZE: usize = virtio_input_event::SIZE;
const EVENT_BUFFER_LEN_MAX: usize = 64 * EVENT_SIZE;
@ -148,7 +149,9 @@ impl EventDevice {
}
pub fn recv_event_encoded(&self) -> io::Result<virtio_input_event> {
zerocopy_from_reader::<_, virtio_input_event>(&self.event_socket)
let mut event = virtio_input_event::new_zeroed();
(&self.event_socket).read_exact(event.as_bytes_mut())?;
Ok(event)
}
}

View file

@ -29,7 +29,6 @@ use base::Result as SysResult;
use base::ScmSocket;
use base::SharedMemory;
use base::SIGRTMIN;
use data_model::zerocopy_from_slice;
use kvm::dirty_log_bitmap_size;
use kvm::Datamatch;
use kvm::IoeventAddress;
@ -37,6 +36,10 @@ use kvm::IrqRoute;
use kvm::IrqSource;
use kvm::PicId;
use kvm::Vm;
use kvm_sys::kvm_clock_data;
use kvm_sys::kvm_ioapic_state;
use kvm_sys::kvm_pic_state;
use kvm_sys::kvm_pit_state2;
use libc::pid_t;
use libc::waitpid;
use libc::EINVAL;
@ -56,6 +59,7 @@ use protos::plugin::*;
use sync::Mutex;
use vm_memory::GuestAddress;
use zerocopy::AsBytes;
use zerocopy::FromBytes;
use super::*;
@ -79,22 +83,25 @@ fn set_vm_state(
state: &[u8],
) -> SysResult<()> {
match state_set.enum_value().map_err(|_| SysError::new(EINVAL))? {
main_request::StateSet::PIC0 => vm.set_pic_state(
PicId::Primary,
zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?,
),
main_request::StateSet::PIC1 => vm.set_pic_state(
PicId::Secondary,
zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?,
),
main_request::StateSet::PIC0 => {
let pic_state = kvm_pic_state::read_from(state).ok_or(SysError::new(EINVAL))?;
vm.set_pic_state(PicId::Primary, &pic_state)
}
main_request::StateSet::PIC1 => {
let pic_state = kvm_pic_state::read_from(state).ok_or(SysError::new(EINVAL))?;
vm.set_pic_state(PicId::Secondary, &pic_state)
}
main_request::StateSet::IOAPIC => {
vm.set_ioapic_state(zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?)
let ioapic_state = kvm_ioapic_state::read_from(state).ok_or(SysError::new(EINVAL))?;
vm.set_ioapic_state(&ioapic_state)
}
main_request::StateSet::PIT => {
vm.set_pit_state(zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?)
let pit_state = kvm_pit_state2::read_from(state).ok_or(SysError::new(EINVAL))?;
vm.set_pit_state(&pit_state)
}
main_request::StateSet::CLOCK => {
vm.set_clock(zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?)
let clock_data = kvm_clock_data::read_from(state).ok_or(SysError::new(EINVAL))?;
vm.set_clock(&clock_data)
}
}
}

View file

@ -19,13 +19,19 @@ use std::sync::RwLock;
use base::error;
use base::LayoutAllocation;
use data_model::zerocopy_from_slice;
use kvm::CpuId;
use kvm::Vcpu;
use kvm_sys::kvm_debugregs;
use kvm_sys::kvm_enable_cap;
use kvm_sys::kvm_fpu;
use kvm_sys::kvm_lapic_state;
use kvm_sys::kvm_mp_state;
use kvm_sys::kvm_msr_entry;
use kvm_sys::kvm_msrs;
use kvm_sys::kvm_regs;
use kvm_sys::kvm_sregs;
use kvm_sys::kvm_vcpu_events;
use kvm_sys::kvm_xcrs;
use kvm_sys::KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
use libc::EINVAL;
use libc::ENOENT;
@ -40,6 +46,7 @@ use protos::plugin::*;
use static_assertions::const_assert;
use sync::Mutex;
use zerocopy::AsBytes;
use zerocopy::FromBytes;
use super::*;
@ -111,28 +118,36 @@ fn set_vcpu_state_enum_or_unknown(
fn set_vcpu_state(vcpu: &Vcpu, state_set: vcpu_request::StateSet, state: &[u8]) -> SysResult<()> {
match state_set {
vcpu_request::StateSet::REGS => {
vcpu.set_regs(zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?)
let regs = kvm_regs::read_from(state).ok_or(SysError::new(EINVAL))?;
vcpu.set_regs(&regs)
}
vcpu_request::StateSet::SREGS => {
vcpu.set_sregs(zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?)
let sregs = kvm_sregs::read_from(state).ok_or(SysError::new(EINVAL))?;
vcpu.set_sregs(&sregs)
}
vcpu_request::StateSet::FPU => {
vcpu.set_fpu(zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?)
let fpu = kvm_fpu::read_from(state).ok_or(SysError::new(EINVAL))?;
vcpu.set_fpu(&fpu)
}
vcpu_request::StateSet::DEBUGREGS => {
vcpu.set_debugregs(zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?)
let debugregs = kvm_debugregs::read_from(state).ok_or(SysError::new(EINVAL))?;
vcpu.set_debugregs(&debugregs)
}
vcpu_request::StateSet::XCREGS => {
vcpu.set_xcrs(zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?)
let xcrs = kvm_xcrs::read_from(state).ok_or(SysError::new(EINVAL))?;
vcpu.set_xcrs(&xcrs)
}
vcpu_request::StateSet::LAPIC => {
vcpu.set_lapic(zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?)
let lapic_state = kvm_lapic_state::read_from(state).ok_or(SysError::new(EINVAL))?;
vcpu.set_lapic(&lapic_state)
}
vcpu_request::StateSet::MP => {
vcpu.set_mp_state(zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?)
let mp_state = kvm_mp_state::read_from(state).ok_or(SysError::new(EINVAL))?;
vcpu.set_mp_state(&mp_state)
}
vcpu_request::StateSet::EVENTS => {
vcpu.set_vcpu_events(zerocopy_from_slice(state).ok_or(SysError::new(EINVAL))?)
let vcpu_events = kvm_vcpu_events::read_from(state).ok_or(SysError::new(EINVAL))?;
vcpu.set_vcpu_events(&vcpu_events)
}
}
}

View file

@ -18,7 +18,6 @@ anyhow = "*"
base = { path = "../../base" }
bitflags = "2.3"
cfg-if = "1.0.0"
data_model = { path = "../../common/data_model" }
enumn = "0.1.0"
libc = ">=0.2.39"
remain = "*"

View file

@ -12,7 +12,6 @@ use base::AsRawDescriptor;
use base::Event;
use base::RawDescriptor;
use base::INVALID_DESCRIPTOR;
use data_model::zerocopy_from_reader;
use zerocopy::AsBytes;
use zerocopy::FromBytes;
@ -552,7 +551,8 @@ impl Master {
for _ in 0..body_reply.value {
regions.push(
// Can't fail because the input is the correct size.
zerocopy_from_reader(&buf_reply[offset..(offset + struct_size)]).unwrap(),
VhostSharedMemoryRegion::read_from(&buf_reply[offset..(offset + struct_size)])
.unwrap(),
);
offset += struct_size;
}