Skip to content

Commit b2eaf98

Browse files
committed
mmap: drop file-offset checking
When mmap-ing a file-like object, vm-memory was trying to validate the the range [offset, offset+len) was valid in the file. However, our homegrown check had lots of edge cases where it gave false-positives (e.g. it rejected things that should really be working, such as vfio devices, or fds that cannot be seeked like guest_memfd), and trying to implement a check that works for all of these is in the end wasted effort anyway, because the kernel validates all this as part of the mmap syscall anyway. So just drop these checks in favor of failing at mmap-time. Drop a test case about mmap-ing a file of size 0 - this works because the mmap will simply grow the file. Signed-off-by: Patrick Roy <[email protected]>
1 parent 2b7967c commit b2eaf98

File tree

4 files changed

+5
-55
lines changed

4 files changed

+5
-55
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
`Bytes::write_to`, `Bytes::write_all_to`, `GuestMemory::as_slice`, `GuestMemory::as_slice_mut`, `GuestMemory::with_regions`,
2020
`GuestMemory::with_regions_mut`, `GuestMemory::map_and_fold`, `VolatileSlice::as_ptr`, `VolatileRef::as_ptr`, and
2121
`VolatileArrayRef::as_ptr`.
22+
- \[[#320](https://github.com/rust-vmm/vm-memory/pull/320)\] Drop `check_file_offset` check when using `MmapRegionBuilder`.
23+
The `mmap(2)` syscall itself already validates that offset and length are valid, and trying to replicate this check
24+
in userspace ended up being imperfect.
2225

2326
## \[v0.16.1\]
2427

src/mmap/mod.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
//! This implementation is mmap-ing the memory of the guest into the current process.
1414
1515
use std::borrow::Borrow;
16-
#[cfg(target_family = "unix")]
17-
use std::io::{Seek, SeekFrom};
1816
use std::ops::Deref;
1917
use std::result;
2018
use std::sync::atomic::Ordering;
@@ -72,34 +70,6 @@ pub enum Error {
7270
UnsortedMemoryRegions,
7371
}
7472

75-
// TODO: use this for Windows as well after we redefine the Error type there.
76-
#[cfg(target_family = "unix")]
77-
/// Checks if a mapping of `size` bytes fits at the provided `file_offset`.
78-
///
79-
/// For a borrowed `FileOffset` and size, this function checks whether the mapping does not
80-
/// extend past EOF, and that adding the size to the file offset does not lead to overflow.
81-
pub fn check_file_offset(
82-
file_offset: &FileOffset,
83-
size: usize,
84-
) -> result::Result<(), MmapRegionError> {
85-
let mut file = file_offset.file();
86-
let start = file_offset.start();
87-
88-
if let Some(end) = start.checked_add(size as u64) {
89-
let filesize = file
90-
.seek(SeekFrom::End(0))
91-
.map_err(MmapRegionError::SeekEnd)?;
92-
file.rewind().map_err(MmapRegionError::SeekStart)?;
93-
if filesize < end {
94-
return Err(MmapRegionError::MappingPastEof);
95-
}
96-
} else {
97-
return Err(MmapRegionError::InvalidOffsetLength);
98-
}
99-
100-
Ok(())
101-
}
102-
10373
/// [`GuestMemoryRegion`](trait.GuestMemoryRegion.html) implementation that mmaps the guest's
10474
/// memory region in the current process.
10575
///

src/mmap/unix.rs

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use std::result;
1717

1818
use crate::bitmap::{Bitmap, NewBitmap, BS};
1919
use crate::guest_memory::FileOffset;
20-
use crate::mmap::check_file_offset;
2120
use crate::volatile_memory::{self, VolatileMemory, VolatileSlice};
2221

2322
/// Error conditions that may arise when creating a new `MmapRegion` object.
@@ -41,12 +40,6 @@ pub enum Error {
4140
/// The `mmap` call returned an error.
4241
#[error("{0}")]
4342
Mmap(io::Error),
44-
/// Seeking the end of the file returned an error.
45-
#[error("Error seeking the end of the file: {0}")]
46-
SeekEnd(io::Error),
47-
/// Seeking the start of the file returned an error.
48-
#[error("Error seeking the start of the file: {0}")]
49-
SeekStart(io::Error),
5043
}
5144

5245
pub type Result<T> = result::Result<T, Error>;
@@ -137,7 +130,6 @@ impl<B: Bitmap> MmapRegionBuilder<B> {
137130
}
138131

139132
let (fd, offset) = if let Some(ref f_off) = self.file_offset {
140-
check_file_offset(f_off, self.size)?;
141133
(f_off.file().as_raw_fd(), f_off.start())
142134
} else {
143135
(-1, 0)
@@ -558,16 +550,9 @@ mod tests {
558550
prot,
559551
flags,
560552
);
561-
assert_eq!(format!("{:?}", r.unwrap_err()), "InvalidOffsetLength");
562-
563-
// Offset + size is greater than the size of the file (which is 0 at this point).
564-
let r = MmapRegion::build(
565-
Some(FileOffset::from_arc(a.clone(), offset)),
566-
size,
567-
prot,
568-
flags,
553+
assert!(
554+
matches!(r.unwrap_err(), Error::Mmap(err) if err.raw_os_error() == Some(libc::EINVAL))
569555
);
570-
assert_eq!(format!("{:?}", r.unwrap_err()), "MappingPastEof");
571556

572557
// MAP_FIXED was specified among the flags.
573558
let r = MmapRegion::build(

src/mmap/xen.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ use tests::ioctl_with_ref;
2626

2727
use crate::bitmap::{Bitmap, NewBitmap, BS};
2828
use crate::guest_memory::{FileOffset, GuestAddress};
29-
use crate::mmap::check_file_offset;
3029
use crate::volatile_memory::{self, VolatileMemory, VolatileSlice};
3130

3231
/// Error conditions that may arise when creating a new `MmapRegion` object.
@@ -44,12 +43,6 @@ pub enum Error {
4443
/// The `mmap` call returned an error.
4544
#[error("{0}")]
4645
Mmap(io::Error),
47-
/// Seeking the end of the file returned an error.
48-
#[error("Error seeking the end of the file: {0}")]
49-
SeekEnd(io::Error),
50-
/// Seeking the start of the file returned an error.
51-
#[error("Error seeking the start of the file: {0}")]
52-
SeekStart(io::Error),
5346
/// Invalid file offset.
5447
#[error("Invalid file offset")]
5548
InvalidFileOffset,
@@ -524,7 +517,6 @@ struct MmapXenUnix(MmapUnix);
524517
impl MmapXenUnix {
525518
fn new(range: &MmapRange) -> Result<Self> {
526519
let (fd, offset) = if let Some(ref f_off) = range.file_offset {
527-
check_file_offset(f_off, range.size)?;
528520
(f_off.file().as_raw_fd(), f_off.start())
529521
} else {
530522
(-1, 0)

0 commit comments

Comments
 (0)