summary refs log tree commit diff
path: root/devices/src/virtio/mod.rs
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2019-08-09 14:25:03 -0700
committerCommit Bot <commit-bot@chromium.org>2019-08-16 07:20:21 +0000
commit58010b27310cc27df542294f81a19ea95feded5f (patch)
treeb9dc4cc8203edc1b4c5b26bed7c9fc585acc076d /devices/src/virtio/mod.rs
parent35a9d838dbb92b89e8baef380a550b8d8a4b15ad (diff)
downloadcrosvm-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.rs27
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);
+                }
+            }
+        }
+    }
+}