Skip to content

Commit b763666

Browse files
committed
tmp: call mmap outselves
vm-memory has faulty validation logic that prevents us from mmap-ing guest_memfds, so just bypass that by calling mmap ourselves for the time being. See also rust-vmm/vm-memory#320 Signed-off-by: Patrick Roy <roypat@amazon.co.uk>
1 parent a849eda commit b763666

File tree

1 file changed

+31
-4
lines changed

1 file changed

+31
-4
lines changed

src/vmm/src/vstate/memory.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::fs::File;
99
use std::io::{Read, Seek, SeekFrom};
1010
use std::mem::ManuallyDrop;
1111
use std::os::fd::AsRawFd;
12+
use std::ptr::null_mut;
1213
use std::sync::Arc;
1314

1415
use kvm_bindings::{KVM_MEM_LOG_DIRTY_PAGES, kvm_userspace_memory_region2};
@@ -56,6 +57,8 @@ pub enum MemoryError {
5657
MemfdSetLen(std::io::Error),
5758
/// Total sum of memory regions exceeds largest possible file offset
5859
OffsetTooLarge,
60+
/// Error calling mmap: {0}
61+
Mmap(std::io::Error),
5962
}
6063

6164
/// Newtype that implements [`ReadVolatile`] and [`WriteVolatile`] if `T` implements `Read` or
@@ -249,16 +252,40 @@ pub fn create(
249252
let mut builder = MmapRegionBuilder::new_with_bitmap(
250253
size,
251254
track_dirty_pages.then(|| AtomicBitmap::with_len(size)),
252-
)
253-
.with_mmap_prot(libc::PROT_READ | libc::PROT_WRITE)
254-
.with_mmap_flags(libc::MAP_NORESERVE | mmap_flags);
255+
);
255256

256-
if let Some(ref file) = file {
257+
// when computing offset below we ensure it fits into i64
258+
#[allow(clippy::cast_possible_wrap)]
259+
let (fd, fd_off) = if let Some(ref file) = file {
257260
let file_offset = FileOffset::from_arc(Arc::clone(file), offset);
258261

259262
builder = builder.with_file_offset(file_offset);
263+
264+
(file.as_raw_fd(), offset as libc::off_t)
265+
} else {
266+
(-1, 0)
267+
};
268+
269+
// SAFETY: the arguments to mmap cannot cause any memory unsafety in the rust sense
270+
let ptr = unsafe {
271+
libc::mmap(
272+
null_mut(),
273+
size,
274+
libc::PROT_READ | libc::PROT_WRITE,
275+
libc::MAP_NORESERVE | mmap_flags,
276+
fd,
277+
fd_off,
278+
)
279+
};
280+
281+
if ptr == libc::MAP_FAILED {
282+
return Err(MemoryError::Mmap(std::io::Error::last_os_error()));
260283
}
261284

285+
// SAFETY: we check above that mmap succeeded, and the size we passed to builder is the
286+
// same as the size of the mmap area.
287+
let builder = unsafe { builder.with_raw_mmap_pointer(ptr.cast()) };
288+
262289
offset = match offset.checked_add(size as u64) {
263290
None => return Err(MemoryError::OffsetTooLarge),
264291
Some(new_off) if new_off >= i64::MAX as u64 => {

0 commit comments

Comments
 (0)