diff options
author | Daniel Verkamp <dverkamp@chromium.org> | 2019-08-09 14:25:03 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-08-16 07:20:21 +0000 |
commit | 58010b27310cc27df542294f81a19ea95feded5f (patch) | |
tree | b9dc4cc8203edc1b4c5b26bed7c9fc585acc076d /devices/src/virtio/mod.rs | |
parent | 35a9d838dbb92b89e8baef380a550b8d8a4b15ad (diff) | |
download | crosvm-58010b27310cc27df542294f81a19ea95feded5f.tar crosvm-58010b27310cc27df542294f81a19ea95feded5f.tar.gz crosvm-58010b27310cc27df542294f81a19ea95feded5f.tar.bz2 crosvm-58010b27310cc27df542294f81a19ea95feded5f.tar.lz crosvm-58010b27310cc27df542294f81a19ea95feded5f.tar.xz crosvm-58010b27310cc27df542294f81a19ea95feded5f.tar.zst crosvm-58010b27310cc27df542294f81a19ea95feded5f.zip |
devices: virtio: add copy_config() helper function
Add a new virtio configuration copying function to replace all of the slightly varying read_config() and write_config() implementations in our virtio devices. This replaces a lot of tricky bounds-checking code with a single central implementation, simplifying the devices to a single call to copy_config() in most cases. The balloon device is also changed to represent its config space as a DataInit struct to match most other devices and remove several unwrap() calls. BUG=None TEST=./build_test TEST=Boot vm_kernel+vm_rootfs in crosvm TEST=Start Crostini on nami Change-Id: Ia49bd6dbe609d17455b9562086bc0b24f327be3f Signed-off-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1749562 Reviewed-by: Dylan Reid <dgreid@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com>
Diffstat (limited to 'devices/src/virtio/mod.rs')
-rw-r--r-- | devices/src/virtio/mod.rs | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/devices/src/virtio/mod.rs b/devices/src/virtio/mod.rs index 0970b86..49f4355 100644 --- a/devices/src/virtio/mod.rs +++ b/devices/src/virtio/mod.rs @@ -43,6 +43,9 @@ pub use self::virtio_device::*; pub use self::virtio_pci_device::*; pub use self::wl::*; +use std::cmp; +use std::convert::TryFrom; + const DEVICE_ACKNOWLEDGE: u32 = 0x01; const DEVICE_DRIVER: u32 = 0x02; const DEVICE_DRIVER_OK: u32 = 0x04; @@ -88,3 +91,27 @@ pub fn type_to_str(type_: u32) -> Option<&'static str> { _ => return None, }) } + +/// Copy virtio device configuration data from a subslice of `src` to a subslice of `dst`. +/// Unlike std::slice::copy_from_slice(), this function copies as much as possible within +/// the common subset of the two slices, truncating the requested range instead of +/// panicking if the slices do not match in size. +/// +/// `dst_offset` and `src_offset` specify the starting indexes of the `dst` and `src` +/// slices, respectively; if either index is out of bounds, this function is a no-op +/// rather than panicking. This makes it safe to call with arbitrary user-controlled +/// inputs. +pub fn copy_config(dst: &mut [u8], dst_offset: u64, src: &[u8], src_offset: u64) { + if let Ok(dst_offset) = usize::try_from(dst_offset) { + if let Ok(src_offset) = usize::try_from(src_offset) { + if let Some(dst_slice) = dst.get_mut(dst_offset..) { + if let Some(src_slice) = src.get(src_offset..) { + let len = cmp::min(dst_slice.len(), src_slice.len()); + let dst_subslice = &mut dst_slice[0..len]; + let src_subslice = &src_slice[0..len]; + dst_subslice.copy_from_slice(src_subslice); + } + } + } + } +} |