1 // Copyright 2020 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use base::VolatileSlice; 6 use remain::sorted; 7 use thiserror::Error as ThisError; 8 9 #[sorted] 10 #[derive(ThisError, Debug)] 11 pub enum Error { 12 /// Invalid offset or length given for an iovec in backing memory. 13 #[error("Invalid offset/len for getting a slice from {0} with len {1}.")] 14 InvalidOffset(u64, usize), 15 } 16 pub type Result<T> = std::result::Result<T, Error>; 17 18 /// Used to index subslices of backing memory. Like an iovec, but relative to the start of the 19 /// backing memory instead of an absolute pointer. 20 /// The backing memory referenced by the region can be an array, an mmapped file, or guest memory. 21 /// The offset is a u64 to allow having file or guest offsets >4GB when run on a 32bit host. 22 #[derive(Copy, Clone, Debug, PartialEq, Eq)] 23 pub struct MemRegion { 24 pub offset: u64, 25 pub len: usize, 26 } 27 28 /// Iterator over an ordered list of [`MemRegion`]. 29 /// 30 /// In addition to the usual iterator operations, `MemRegionIter` provides extra functionality that 31 /// allows subslicing individual memory regions without mutating the underlying list: 32 /// - [`skip_bytes()`](Self::skip_bytes): Advance the iterator some number of bytes, potentially 33 /// starting iteration in the middle of a `MemRegion`. 34 /// - [`take_bytes()`](Self::take_bytes): Truncate the iterator at some number of bytes, potentially 35 /// ending iteration in the middle of a `MemRegion`. 36 /// 37 /// The order of subslicing operations matters - limiting length followed by skipping bytes is not 38 /// the same as skipping bytes followed by limiting length. 39 #[derive(Clone)] 40 pub struct MemRegionIter<'a> { 41 regions: &'a [MemRegion], 42 skip_bytes: usize, 43 remaining_bytes: usize, 44 } 45 46 impl<'a> MemRegionIter<'a> { 47 /// Create a new `MemRegion` iterator over a slice of `MemRegion`. 48 /// 49 /// By default, the `MemRegionIter` will iterate over each `MemRegion` in the list in its 50 /// entirety. Call [`skip_bytes()`](Self::skip_bytes) and/or 51 /// [`take_bytes()`](Self::take_bytes) to limit iteration to a sub-slice of the specified 52 /// `regions` list. new(regions: &'a [MemRegion]) -> Self53 pub fn new(regions: &'a [MemRegion]) -> Self { 54 MemRegionIter { 55 regions, 56 skip_bytes: 0, 57 remaining_bytes: usize::MAX, 58 } 59 } 60 61 /// Advance the iterator by `offset` bytes. 62 /// 63 /// This may place the iterator in the middle of a [`MemRegion`]; in this case, the offset and 64 /// length of the next [`MemRegion`] returned by [`next()`](Self::next) will be adjusted to 65 /// account for the offset. 66 /// 67 /// Skipping more than the remaining length of an iterator is not an error; if `offset` is 68 /// greater than or equal to the total number of remaining bytes, future calls to 69 /// [`next()`](Self::next) will simply return `None`. skip_bytes(self, offset: usize) -> Self70 pub fn skip_bytes(self, offset: usize) -> Self { 71 MemRegionIter { 72 regions: self.regions, 73 skip_bytes: self.skip_bytes.saturating_add(offset), 74 remaining_bytes: self.remaining_bytes.saturating_sub(offset), 75 } 76 } 77 78 /// Truncate the length of the iterator to `max` bytes at most. 79 /// 80 /// This may cause the final [`MemRegion`] returned by [`next()`](Self::next) to be adjusted so 81 /// that its length does not cause the total number of bytes to exceed the requested `max`. 82 /// 83 /// If less than `max` bytes remain in the iterator already, this function will have no effect. 84 /// 85 /// Only truncation is supported; an iterator cannot be extended, even if it was truncated by a 86 /// previous call to `take_bytes()`. take_bytes(self, max: usize) -> Self87 pub fn take_bytes(self, max: usize) -> Self { 88 MemRegionIter { 89 regions: self.regions, 90 skip_bytes: self.skip_bytes, 91 remaining_bytes: self.remaining_bytes.min(max), 92 } 93 } 94 } 95 96 impl Iterator for MemRegionIter<'_> { 97 type Item = MemRegion; 98 next(&mut self) -> Option<Self::Item>99 fn next(&mut self) -> Option<Self::Item> { 100 if self.remaining_bytes == 0 { 101 return None; 102 } 103 104 while let Some((first, remaining)) = self.regions.split_first() { 105 // This call to `next()` will consume `first`; future calls will start with `remaining`. 106 self.regions = remaining; 107 108 // If skip_bytes encompasses this entire region, skip to the next region. 109 // This also skips zero-length regions, which should not be returned by the iterator. 110 if self.skip_bytes >= first.len { 111 self.skip_bytes -= first.len; 112 continue; 113 } 114 115 // Adjust the current region and reset `self.skip_bytes` to 0 to fully consume it. 116 let mut region = MemRegion { 117 offset: first.offset + self.skip_bytes as u64, 118 len: first.len - self.skip_bytes, 119 }; 120 self.skip_bytes = 0; 121 122 // If this region is at least as large as `remaining_bytes`, truncate the region and set 123 // `regions` to an empty slice to terminate iteration in future calls to `next()`. 124 if region.len >= self.remaining_bytes { 125 region.len = self.remaining_bytes; 126 self.remaining_bytes = 0; 127 self.regions = &[]; 128 } else { 129 // Consume and return the full region. 130 self.remaining_bytes -= region.len; 131 } 132 133 // This should never return a zero-length region (should be handled by the 134 // `remaining_bytes == 0` early return and zero-length region skipping above). 135 debug_assert_ne!(region.len, 0); 136 return Some(region); 137 } 138 139 None 140 } 141 } 142 143 /// Trait for memory that can yield both iovecs in to the backing memory. 144 /// # Safety 145 /// Must be OK to modify the backing memory without owning a mut able reference. For example, 146 /// this is safe for GuestMemory and VolatileSlices in crosvm as those types guarantee they are 147 /// dealt with as volatile. 148 pub unsafe trait BackingMemory { 149 /// Returns VolatileSlice pointing to the backing memory. This is most commonly unsafe. 150 /// To implement this safely the implementor must guarantee that the backing memory can be 151 /// modified out of band without affecting safety guarantees. get_volatile_slice(&self, mem_range: MemRegion) -> Result<VolatileSlice>152 fn get_volatile_slice(&self, mem_range: MemRegion) -> Result<VolatileSlice>; 153 } 154 155 /// Wrapper to be used for passing a Vec in as backing memory for asynchronous operations. The 156 /// wrapper owns a Vec according to the borrow checker. It is loaning this vec out to the kernel(or 157 /// other modifiers) through the `BackingMemory` trait. This allows multiple modifiers of the array 158 /// in the `Vec` while this struct is alive. The data in the Vec is loaned to the kernel not the 159 /// data structure itself, the length, capacity, and pointer to memory cannot be modified. 160 /// To ensure that those operations can be done safely, no access is allowed to the `Vec`'s memory 161 /// starting at the time that `VecIoWrapper` is constructed until the time it is turned back in to a 162 /// `Vec` using `to_inner`. The returned `Vec` is guaranteed to be valid as any combination of bits 163 /// in a `Vec` of `u8` is valid. 164 pub struct VecIoWrapper { 165 inner: Box<[u8]>, 166 } 167 168 impl From<Vec<u8>> for VecIoWrapper { from(vec: Vec<u8>) -> Self169 fn from(vec: Vec<u8>) -> Self { 170 VecIoWrapper { inner: vec.into() } 171 } 172 } 173 174 impl From<VecIoWrapper> for Vec<u8> { from(v: VecIoWrapper) -> Vec<u8>175 fn from(v: VecIoWrapper) -> Vec<u8> { 176 v.inner.into() 177 } 178 } 179 180 impl VecIoWrapper { 181 /// Get the length of the Vec that is wrapped. 182 #[cfg_attr(windows, allow(dead_code))] len(&self) -> usize183 pub fn len(&self) -> usize { 184 self.inner.len() 185 } 186 is_empty(&self) -> bool187 pub fn is_empty(&self) -> bool { 188 self.len() == 0 189 } 190 191 // Check that the offsets are all valid in the backing vec. check_addrs(&self, mem_range: &MemRegion) -> Result<()>192 fn check_addrs(&self, mem_range: &MemRegion) -> Result<()> { 193 let end = mem_range 194 .offset 195 .checked_add(mem_range.len as u64) 196 .ok_or(Error::InvalidOffset(mem_range.offset, mem_range.len))?; 197 if end > self.inner.len() as u64 { 198 return Err(Error::InvalidOffset(mem_range.offset, mem_range.len)); 199 } 200 Ok(()) 201 } 202 } 203 204 // SAFETY: 205 // Safe to implement BackingMemory as the vec is only accessible inside the wrapper and these iovecs 206 // are the only thing allowed to modify it. Nothing else can get a reference to the vec until all 207 // iovecs are dropped because they borrow Self. Nothing can borrow the owned inner vec until self 208 // is consumed by `into`, which can't happen if there are outstanding mut borrows. 209 unsafe impl BackingMemory for VecIoWrapper { get_volatile_slice(&self, mem_range: MemRegion) -> Result<VolatileSlice<'_>>210 fn get_volatile_slice(&self, mem_range: MemRegion) -> Result<VolatileSlice<'_>> { 211 self.check_addrs(&mem_range)?; 212 // SAFETY: 213 // Safe because the mem_range range is valid in the backing memory as checked above. 214 unsafe { 215 Ok(VolatileSlice::from_raw_parts( 216 self.inner.as_ptr().add(mem_range.offset as usize) as *mut _, 217 mem_range.len, 218 )) 219 } 220 } 221 } 222 223 #[cfg(test)] 224 mod tests { 225 use super::*; 226 227 #[test] mem_region_iter_empty()228 fn mem_region_iter_empty() { 229 let mut iter = MemRegionIter::new(&[]); 230 assert_eq!(iter.next(), None); 231 } 232 233 #[test] mem_region_iter_one()234 fn mem_region_iter_one() { 235 let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]); 236 assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 })); 237 assert_eq!(iter.next(), None); 238 } 239 240 #[test] mem_region_iter_one_len_usize_max()241 fn mem_region_iter_one_len_usize_max() { 242 let mut iter = MemRegionIter::new(&[MemRegion { 243 offset: 0, 244 len: usize::MAX, 245 }]); 246 assert_eq!( 247 iter.next(), 248 Some(MemRegion { 249 offset: 0, 250 len: usize::MAX 251 }) 252 ); 253 assert_eq!(iter.next(), None); 254 } 255 256 #[test] mem_region_iter_one_len_zero()257 fn mem_region_iter_one_len_zero() { 258 let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 0 }]); 259 assert_eq!(iter.next(), None); 260 } 261 262 #[test] mem_region_iter_one_skip_partial()263 fn mem_region_iter_one_skip_partial() { 264 let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).skip_bytes(1); 265 assert_eq!(iter.next(), Some(MemRegion { offset: 1, len: 3 })); 266 assert_eq!(iter.next(), None); 267 } 268 269 #[test] mem_region_iter_one_skip_full()270 fn mem_region_iter_one_skip_full() { 271 let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).skip_bytes(4); 272 assert_eq!(iter.next(), None); 273 } 274 275 #[test] mem_region_iter_one_skip_excess()276 fn mem_region_iter_one_skip_excess() { 277 let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).skip_bytes(5); 278 assert_eq!(iter.next(), None); 279 } 280 281 #[test] mem_region_iter_one_take_zero()282 fn mem_region_iter_one_take_zero() { 283 let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).take_bytes(0); 284 assert_eq!(iter.next(), None); 285 } 286 287 #[test] mem_region_iter_one_take_partial()288 fn mem_region_iter_one_take_partial() { 289 let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).take_bytes(1); 290 assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 1 })); 291 assert_eq!(iter.next(), None); 292 } 293 294 #[test] mem_region_iter_one_take_full()295 fn mem_region_iter_one_take_full() { 296 let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).take_bytes(4); 297 assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 })); 298 assert_eq!(iter.next(), None); 299 } 300 301 #[test] mem_region_iter_one_take_excess()302 fn mem_region_iter_one_take_excess() { 303 let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]).take_bytes(5); 304 assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 })); 305 assert_eq!(iter.next(), None); 306 } 307 308 #[test] mem_region_iter_one_take_skip()309 fn mem_region_iter_one_take_skip() { 310 let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]) 311 .take_bytes(2) 312 .skip_bytes(1); 313 assert_eq!(iter.next(), Some(MemRegion { offset: 1, len: 1 })); 314 assert_eq!(iter.next(), None); 315 } 316 317 #[test] mem_region_iter_one_skip_take()318 fn mem_region_iter_one_skip_take() { 319 let mut iter = MemRegionIter::new(&[MemRegion { offset: 0, len: 4 }]) 320 .skip_bytes(1) 321 .take_bytes(2); 322 assert_eq!(iter.next(), Some(MemRegion { offset: 1, len: 2 })); 323 assert_eq!(iter.next(), None); 324 } 325 326 #[test] mem_region_iter_two()327 fn mem_region_iter_two() { 328 let mut iter = MemRegionIter::new(&[ 329 MemRegion { offset: 0, len: 4 }, 330 MemRegion { offset: 8, len: 2 }, 331 ]); 332 assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 })); 333 assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 2 })); 334 assert_eq!(iter.next(), None); 335 } 336 337 #[test] mem_region_iter_two_skip_partial()338 fn mem_region_iter_two_skip_partial() { 339 let mut iter = MemRegionIter::new(&[ 340 MemRegion { offset: 0, len: 4 }, 341 MemRegion { offset: 8, len: 2 }, 342 ]) 343 .skip_bytes(1); 344 assert_eq!(iter.next(), Some(MemRegion { offset: 1, len: 3 })); 345 assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 2 })); 346 assert_eq!(iter.next(), None); 347 } 348 349 #[test] mem_region_iter_two_skip_full()350 fn mem_region_iter_two_skip_full() { 351 let mut iter = MemRegionIter::new(&[ 352 MemRegion { offset: 0, len: 4 }, 353 MemRegion { offset: 8, len: 2 }, 354 ]) 355 .skip_bytes(4); 356 assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 2 })); 357 assert_eq!(iter.next(), None); 358 } 359 360 #[test] mem_region_iter_two_skip_excess()361 fn mem_region_iter_two_skip_excess() { 362 let mut iter = MemRegionIter::new(&[ 363 MemRegion { offset: 0, len: 4 }, 364 MemRegion { offset: 8, len: 2 }, 365 ]) 366 .skip_bytes(5); 367 assert_eq!(iter.next(), Some(MemRegion { offset: 9, len: 1 })); 368 assert_eq!(iter.next(), None); 369 } 370 371 #[test] mem_region_iter_two_skip_multi()372 fn mem_region_iter_two_skip_multi() { 373 let mut iter = MemRegionIter::new(&[ 374 MemRegion { offset: 0, len: 4 }, 375 MemRegion { offset: 8, len: 2 }, 376 ]) 377 .skip_bytes(6); 378 assert_eq!(iter.next(), None); 379 } 380 381 #[test] mem_region_iter_two_take_partial()382 fn mem_region_iter_two_take_partial() { 383 let mut iter = MemRegionIter::new(&[ 384 MemRegion { offset: 0, len: 4 }, 385 MemRegion { offset: 8, len: 2 }, 386 ]) 387 .take_bytes(1); 388 assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 1 })); 389 assert_eq!(iter.next(), None); 390 } 391 392 #[test] mem_region_iter_two_take_partial2()393 fn mem_region_iter_two_take_partial2() { 394 let mut iter = MemRegionIter::new(&[ 395 MemRegion { offset: 0, len: 4 }, 396 MemRegion { offset: 8, len: 2 }, 397 ]) 398 .take_bytes(5); 399 assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 })); 400 assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 1 })); 401 assert_eq!(iter.next(), None); 402 } 403 404 #[test] mem_region_iter_two_take_full()405 fn mem_region_iter_two_take_full() { 406 let mut iter = MemRegionIter::new(&[ 407 MemRegion { offset: 0, len: 4 }, 408 MemRegion { offset: 8, len: 2 }, 409 ]) 410 .take_bytes(6); 411 assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 })); 412 assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 2 })); 413 assert_eq!(iter.next(), None); 414 } 415 416 #[test] mem_region_iter_two_take_excess()417 fn mem_region_iter_two_take_excess() { 418 let mut iter = MemRegionIter::new(&[ 419 MemRegion { offset: 0, len: 4 }, 420 MemRegion { offset: 8, len: 2 }, 421 ]) 422 .take_bytes(7); 423 assert_eq!(iter.next(), Some(MemRegion { offset: 0, len: 4 })); 424 assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 2 })); 425 assert_eq!(iter.next(), None); 426 } 427 428 #[test] mem_region_iter_embedded_zero_len()429 fn mem_region_iter_embedded_zero_len() { 430 let mut iter = MemRegionIter::new(&[ 431 MemRegion { offset: 0, len: 4 }, 432 MemRegion { offset: 8, len: 2 }, 433 MemRegion { offset: 9, len: 0 }, 434 MemRegion { offset: 16, len: 5 }, 435 MemRegion { offset: 6, len: 0 }, 436 MemRegion { offset: 24, len: 9 }, 437 ]) 438 .skip_bytes(2) 439 .take_bytes(12); 440 assert_eq!(iter.next(), Some(MemRegion { offset: 2, len: 2 })); 441 assert_eq!(iter.next(), Some(MemRegion { offset: 8, len: 2 })); 442 assert_eq!(iter.next(), Some(MemRegion { offset: 16, len: 5 })); 443 assert_eq!(iter.next(), Some(MemRegion { offset: 24, len: 3 })); 444 assert_eq!(iter.next(), None); 445 } 446 447 #[test] mem_region_iter_skip_multi()448 fn mem_region_iter_skip_multi() { 449 let mut iter = MemRegionIter::new(&[ 450 MemRegion { offset: 0, len: 4 }, 451 MemRegion { offset: 8, len: 2 }, 452 MemRegion { offset: 16, len: 5 }, 453 MemRegion { offset: 24, len: 9 }, 454 ]) 455 .skip_bytes(7); 456 assert_eq!(iter.next(), Some(MemRegion { offset: 17, len: 4 })); 457 assert_eq!(iter.next(), Some(MemRegion { offset: 24, len: 9 })); 458 assert_eq!(iter.next(), None); 459 } 460 } 461