From 2fb1969902f8b81466c21df02dfc283732998bbf Mon Sep 17 00:00:00 2001 From: Stephen Barber Date: Mon, 7 Aug 2017 16:01:53 -0700 Subject: [PATCH] sys_util: add read_slice_at_addr to GuestMemory BUG=none TEST=cargo test Change-Id: Ifeda91de37bf83a2e5a00f5e308db786fa5d49d5 Signed-off-by: Stephen Barber Reviewed-on: https://chromium-review.googlesource.com/604934 Reviewed-by: Dylan Reid --- sys_util/src/guest_memory.rs | 30 ++++++++++++++++++++++++++++++ sys_util/src/mmap.rs | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/sys_util/src/guest_memory.rs b/sys_util/src/guest_memory.rs index f8f7874552..4a41e05a15 100644 --- a/sys_util/src/guest_memory.rs +++ b/sys_util/src/guest_memory.rs @@ -155,6 +155,36 @@ impl GuestMemory { }) } + /// Reads to a slice from guest memory at the specified guest address. + /// Returns the number of bytes read. The number of bytes read can + /// be less than the length of the slice if there isn't enough room in the + /// memory region. + /// + /// # Examples + /// * Read a slice of length 16 at guestaddress 0x200. + /// + /// ``` + /// # use sys_util::{GuestAddress, GuestMemory, MemoryMapping}; + /// # fn test_write_u64() -> Result<(), ()> { + /// # let start_addr = GuestAddress(0x1000); + /// # let mut gm = GuestMemory::new(&vec![(start_addr, 0x400)]).map_err(|_| ())?; + /// let buf = &mut [0u8; 16]; + /// let res = gm.read_slice_at_addr(buf, GuestAddress(0x200)); + /// assert_eq!(Ok(16), res); + /// Ok(()) + /// # } + /// ``` + pub fn read_slice_at_addr(&self, + mut buf: &mut [u8], + guest_addr: GuestAddress) + -> Result { + self.do_in_region(guest_addr, move |mapping, offset| { + mapping + .read_slice(buf, offset) + .map_err(|_| Error::InvalidGuestAddress(guest_addr)) + }) + } + /// Reads an object from guest memory at the given guest address. /// Reading from a volatile area isn't strictly safe as it could change /// mid-read. However, as long as the type T is plain old data and can diff --git a/sys_util/src/mmap.rs b/sys_util/src/mmap.rs index 732c4f0648..78f533db2b 100644 --- a/sys_util/src/mmap.rs +++ b/sys_util/src/mmap.rs @@ -25,8 +25,10 @@ pub enum Error { ReadFromSource, /// `mmap` returned the given error. SystemCallFailed(errno::Error), - /// Wrting to memory failed + /// Writing to memory failed WriteToMemory(std::io::Error), + /// Reading from memory failed + ReadFromMemory(std::io::Error), } pub type Result = std::result::Result; @@ -115,7 +117,7 @@ impl MemoryMapping { /// ``` /// # use sys_util::MemoryMapping; /// # let mut mem_map = MemoryMapping::new(1024).unwrap(); - /// let res = mem_map.write_slice(&[1,2,3,4,5], 0); + /// let res = mem_map.write_slice(&[1,2,3,4,5], 256); /// assert!(res.is_ok()); /// assert_eq!(res.unwrap(), 5); /// ``` @@ -132,6 +134,35 @@ impl MemoryMapping { } } + /// Reads to a slice from the memory region at the specified offset. + /// Returns the number of bytes read. The number of bytes read can + /// be less than the length of the slice if there isn't enough room in the + /// memory region. + /// + /// # Examples + /// * Read a slice of size 16 at offset 256. + /// + /// ``` + /// # use sys_util::MemoryMapping; + /// # let mut mem_map = MemoryMapping::new(1024).unwrap(); + /// let buf = &mut [0u8; 16]; + /// let res = mem_map.read_slice(buf, 256); + /// assert!(res.is_ok()); + /// assert_eq!(res.unwrap(), 16); + /// ``` + pub fn read_slice(&self, mut buf: &mut [u8], offset: usize) -> Result { + if offset >= self.size { + return Err(Error::InvalidAddress); + } + unsafe { + // Guest memory can't strictly be modeled as a slice because it is + // volatile. Writing to it with what compiles down to a memcpy + // won't hurt anything as long as we get the bounds checks right. + let slice: &[u8] = &self.as_slice()[offset..]; + Ok(buf.write(slice).map_err(Error::ReadFromMemory)?) + } + } + /// Writes an object to the memory region at the specified offset. /// Returns Ok(()) if the object fits, or Err if it extends past the end. ///