Skip to content

Commit 595b5a7

Browse files
roypatandreeaflorescu
authored andcommitted
Remove VolatileSlice::as_slice/as_mut_slice
As outlined in the previous commit message, these function had only a singular call-site, which could not guarantee the safety invariants were uheld. Since these functions were non-public, removing them is not a breaking change. Signed-off-by: Patrick Roy <[email protected]>
1 parent 7b16aeb commit 595b5a7

File tree

3 files changed

+65
-68
lines changed

3 files changed

+65
-68
lines changed

src/mmap_unix.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::result;
2020
use crate::bitmap::{Bitmap, BS};
2121
use crate::guest_memory::FileOffset;
2222
use crate::mmap::{check_file_offset, NewBitmap};
23-
use crate::volatile_memory::{self, compute_offset, VolatileMemory, VolatileSlice};
23+
use crate::volatile_memory::{self, VolatileMemory, VolatileSlice};
2424

2525
/// Error conditions that may arise when creating a new `MmapRegion` object.
2626
#[derive(Debug)]
@@ -413,17 +413,14 @@ impl<B: Bitmap> VolatileMemory for MmapRegion<B> {
413413
offset: usize,
414414
count: usize,
415415
) -> volatile_memory::Result<VolatileSlice<BS<B>>> {
416-
let end = compute_offset(offset, count)?;
417-
if end > self.size {
418-
return Err(volatile_memory::Error::OutOfBounds { addr: end });
419-
}
416+
let _ = self.compute_end_offset(offset, count)?;
420417

421418
Ok(
422419
// SAFETY: Safe because we checked that offset + count was within our range and we only
423420
// ever hand out volatile accessors.
424421
unsafe {
425422
VolatileSlice::with_bitmap(
426-
(self.addr as usize + offset) as *mut _,
423+
self.addr.add(offset),
427424
count,
428425
self.bitmap.slice_at(offset),
429426
)

src/mmap_windows.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,7 @@ impl<B: Bitmap> VolatileMemory for MmapRegion<B> {
210210
// Safe because we checked that offset + count was within our range and we only ever hand
211211
// out volatile accessors.
212212
Ok(unsafe {
213-
VolatileSlice::with_bitmap(
214-
(self.addr as usize + offset) as *mut _,
215-
count,
216-
self.bitmap.slice_at(offset),
217-
)
213+
VolatileSlice::with_bitmap(self.addr.add(offset), count, self.bitmap.slice_at(offset))
218214
})
219215
}
220216
}

src/volatile_memory.rs

Lines changed: 61 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ use std::mem::{align_of, size_of};
3232
use std::ptr::copy;
3333
use std::ptr::{read_volatile, write_volatile};
3434
use std::result;
35-
use std::slice::{from_raw_parts, from_raw_parts_mut};
3635
use std::sync::atomic::Ordering;
3736
use std::usize;
3837

@@ -352,15 +351,13 @@ impl<'a, B: BitmapSlice> VolatileSlice<'a, B> {
352351
/// The returned subslice is a copy of this slice with the address increased by `offset` bytes
353352
/// and the size set to `count` bytes.
354353
pub fn subslice(&self, offset: usize, count: usize) -> Result<Self> {
355-
let mem_end = compute_offset(offset, count)?;
356-
if mem_end > self.len() {
357-
return Err(Error::OutOfBounds { addr: mem_end });
358-
}
354+
let _ = self.compute_end_offset(offset, count)?;
355+
359356
// SAFETY: This is safe because the pointer is range-checked by compute_end_offset, and
360357
// the lifetime is the same as the original slice.
361358
unsafe {
362359
Ok(VolatileSlice::with_bitmap(
363-
(self.as_ptr() as usize + offset) as *mut u8,
360+
self.as_ptr().add(offset),
364361
count,
365362
self.bitmap.slice_at(offset),
366363
))
@@ -531,30 +528,6 @@ impl<'a, B: BitmapSlice> VolatileSlice<'a, B> {
531528
};
532529
}
533530

534-
/// Returns a slice corresponding to the data in the underlying memory.
535-
///
536-
/// # Safety
537-
///
538-
/// This function is private and only used for the read/write functions. It is not valid in
539-
/// general to take slices of volatile memory.
540-
unsafe fn as_slice(&self) -> &[u8] {
541-
from_raw_parts(self.addr, self.size)
542-
}
543-
544-
/// Returns a mutable slice corresponding to the data in the underlying memory. Writes to the
545-
/// slice have to be tracked manually using the handle returned by `VolatileSlice::bitmap`.
546-
///
547-
/// # Safety
548-
///
549-
/// This function is private and only used for the read/write functions. It is not valid in
550-
/// general to take slices of volatile memory. Mutable accesses performed through the returned
551-
/// slice are not visible to the dirty bitmap tracking functionality, and must be manually
552-
/// recorded using the associated bitmap object.
553-
#[allow(clippy::mut_from_ref)]
554-
unsafe fn as_mut_slice(&self) -> &mut [u8] {
555-
from_raw_parts_mut(self.addr, self.size)
556-
}
557-
558531
/// Checks if the current slice is aligned at `alignment` bytes.
559532
fn check_alignment(&self, alignment: usize) -> Result<()> {
560533
// Check that the desired alignment is a power of two.
@@ -741,20 +714,30 @@ impl<B: BitmapSlice> Bytes<usize> for VolatileSlice<'_, B> {
741714
where
742715
F: Read,
743716
{
744-
let end = self.compute_end_offset(addr, count)?;
745-
// SAFETY: We checked the addr and count so accessing the slice is safe.
746-
// Also, it is safe to overwrite the volatile memory. Accessing the guest
747-
// memory as a mutable slice is OK because nothing assumes another
748-
// thread won't change what is loaded.
749-
let dst = unsafe { &mut self.as_mut_slice()[addr..end] };
717+
let _ = self.compute_end_offset(addr, count)?;
718+
719+
let mut dst = vec![0; count];
720+
750721
let bytes_read = loop {
751-
match src.read(dst) {
722+
match src.read(&mut dst) {
752723
Ok(n) => break n,
753724
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
754725
Err(e) => return Err(Error::IOError(e)),
755726
}
756727
};
757728

729+
// There is no guarantee that the read implementation is well-behaved, see the docs for
730+
// Read::read.
731+
assert!(bytes_read <= count);
732+
733+
// SAFETY: We have checked via compute_end_offset that accessing the specified
734+
// region of guest memory is valid. We asserted that the value returned by `read` is between
735+
// 0 and count (the length of the buffer passed to it), and that the
736+
// regions don't overlap because we allocated the Vec outside of guest memory.
737+
unsafe {
738+
copy_slice(self.as_ptr().add(addr), dst.as_ptr(), bytes_read);
739+
}
740+
758741
self.bitmap.mark_dirty(addr, bytes_read);
759742
Ok(bytes_read)
760743
}
@@ -787,16 +770,22 @@ impl<B: BitmapSlice> Bytes<usize> for VolatileSlice<'_, B> {
787770
where
788771
F: Read,
789772
{
790-
let end = self.compute_end_offset(addr, count)?;
773+
let _ = self.compute_end_offset(addr, count)?;
791774

792-
// SAFETY: It is safe to overwrite the volatile memory. Accessing the guest memory as a
793-
// mutable slice is OK because nothing assumes another thread won't change what is loaded.
794-
// We also manually update the dirty bitmap below.
795-
let dst = unsafe { &mut self.as_mut_slice()[addr..end] };
775+
let mut dst = vec![0; count];
776+
777+
// Read into buffer that can be copied into guest memory
778+
src.read_exact(&mut dst).map_err(Error::IOError)?;
779+
780+
// SAFETY: We have checked via compute_end_offset that accessing the specified
781+
// region of guest memory is valid. We know that `dst` has len `count`, and that the
782+
// regions don't overlap because we allocated the Vec outside of guest memory
783+
unsafe {
784+
copy_slice(self.as_ptr().add(addr), dst.as_ptr(), count);
785+
}
796786

797-
let result = src.read_exact(dst).map_err(Error::IOError);
798787
self.bitmap.mark_dirty(addr, count);
799-
result
788+
Ok(())
800789
}
801790

802791
/// # Examples
@@ -826,14 +815,21 @@ impl<B: BitmapSlice> Bytes<usize> for VolatileSlice<'_, B> {
826815
where
827816
F: Write,
828817
{
829-
let end = self.compute_end_offset(addr, count)?;
818+
let _ = self.compute_end_offset(addr, count)?;
819+
let mut src = Vec::with_capacity(count);
830820
// SAFETY: We checked the addr and count so accessing the slice is safe.
831-
// It is safe to read from volatile memory. Accessing the guest
832-
// memory as a slice is OK because nothing assumes another thread
833-
// won't change what is loaded.
834-
let src = unsafe { &self.as_slice()[addr..end] };
821+
// It is safe to read from volatile memory. The Vec has capacity for exactly `count`
822+
// many bytes, and the memory regions pointed to definitely do not overlap, as we
823+
// allocated src outside of guest memory.
824+
// The call to set_len is safe because the bytes between 0 and count have been initialized
825+
// via copying from guest memory, and the Vec's capacity is `count`
826+
unsafe {
827+
copy_slice(src.as_mut_ptr(), self.as_ptr().add(addr), count);
828+
src.set_len(count);
829+
}
830+
835831
loop {
836-
match dst.write(src) {
832+
match dst.write(&src) {
837833
Ok(n) => break Ok(n),
838834
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
839835
Err(e) => break Err(Error::IOError(e)),
@@ -868,14 +864,22 @@ impl<B: BitmapSlice> Bytes<usize> for VolatileSlice<'_, B> {
868864
where
869865
F: Write,
870866
{
871-
let end = self.compute_end_offset(addr, count)?;
872-
// SAFETY: It is safe to read from volatile memory. Accessing the guest
873-
// memory as a slice is OK because nothing assumes another thread
874-
// won't change what is loaded.
867+
let _ = self.compute_end_offset(addr, count)?;
868+
let mut src = Vec::with_capacity(count);
869+
870+
// SAFETY: We checked the addr and count so accessing the slice is safe.
871+
// It is safe to read from volatile memory. The Vec has capacity for exactly `count`
872+
// many bytes, and the memory regions pointed to definitely do not overlap, as we
873+
// allocated src outside of guest memory.
874+
// The call to set_len is safe because the bytes between 0 and count have been initialized
875+
// via copying from guest memory, and the Vec's capacity is `count`
875876
unsafe {
876-
let src = &self.as_slice()[addr..end];
877-
dst.write_all(src).map_err(Error::IOError)?;
877+
copy_slice(src.as_mut_ptr(), self.as_ptr().add(addr), count);
878+
src.set_len(count);
878879
}
880+
881+
dst.write_all(&src).map_err(Error::IOError)?;
882+
879883
Ok(())
880884
}
881885

@@ -906,7 +910,7 @@ impl<B: BitmapSlice> VolatileMemory for VolatileSlice<'_, B> {
906910
// the lifetime is the same as self.
907911
unsafe {
908912
VolatileSlice::with_bitmap(
909-
(self.addr as usize + offset) as *mut u8,
913+
self.addr.add(offset),
910914
count,
911915
self.bitmap.slice_at(offset),
912916
)

0 commit comments

Comments
 (0)