Skip to content

Commit 4c4be87

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 caca9cc commit 4c4be87

File tree

4 files changed

+38
-12
lines changed

4 files changed

+38
-12
lines changed

src/vmm/src/builder.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,10 +256,7 @@ pub fn build_microvm_for_boot(
256256

257257
Some(InitrdConfig::from_reader(
258258
vmm.vm.guest_memory(),
259-
MaybeBounce::new(
260-
initrd_file.as_fd(),
261-
vm_resources.machine_config.secret_free,
262-
),
259+
MaybeBounce::new(initrd_file.as_fd(), vm_resources.machine_config.secret_free),
263260
u64_to_usize(size),
264261
)?)
265262
}

src/vmm/src/vstate/memory.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
use std::fs::File;
99
use std::io::{Read, Seek, SeekFrom, Write};
10+
use std::os::fd::AsRawFd;
11+
use std::ptr::null_mut;
1012
use std::sync::Arc;
1113

1214
use serde::{Deserialize, Serialize};
@@ -51,6 +53,8 @@ pub enum MemoryError {
5153
MemfdSetLen(std::io::Error),
5254
/// Total sum of memory regions exceeds largest possible file offset
5355
OffsetTooLarge,
56+
/// Error calling mmap: {0}
57+
Mmap(std::io::Error),
5458
}
5559

5660
/// Newtype that implements [`ReadVolatile`] and [`WriteVolatile`] if `T` implements `Read` or
@@ -204,16 +208,40 @@ pub fn create(
204208
let mut builder = MmapRegionBuilder::new_with_bitmap(
205209
size,
206210
track_dirty_pages.then(|| AtomicBitmap::with_len(size)),
207-
)
208-
.with_mmap_prot(libc::PROT_READ | libc::PROT_WRITE)
209-
.with_mmap_flags(libc::MAP_NORESERVE | mmap_flags);
211+
);
210212

211-
if let Some(ref file) = file {
213+
// when computing offset below we ensure it fits into i64
214+
#[allow(clippy::cast_possible_wrap)]
215+
let (fd, fd_off) = if let Some(ref file) = file {
212216
let file_offset = FileOffset::from_arc(Arc::clone(file), offset);
213217

214218
builder = builder.with_file_offset(file_offset);
219+
220+
(file.as_raw_fd(), offset as libc::off_t)
221+
} else {
222+
(-1, 0)
223+
};
224+
225+
// SAFETY: the arguments to mmap cannot cause any memory unsafety in the rust sense
226+
let ptr = unsafe {
227+
libc::mmap(
228+
null_mut(),
229+
size,
230+
libc::PROT_READ | libc::PROT_WRITE,
231+
libc::MAP_NORESERVE | mmap_flags,
232+
fd,
233+
fd_off,
234+
)
235+
};
236+
237+
if ptr == libc::MAP_FAILED {
238+
return Err(MemoryError::Mmap(std::io::Error::last_os_error()));
215239
}
216240

241+
// SAFETY: we check above that mmap succeeded, and the size we passed to builder is the
242+
// same as the size of the mmap area.
243+
let builder = unsafe { builder.with_raw_mmap_pointer(ptr.cast()) };
244+
217245
offset = match offset.checked_add(size as u64) {
218246
None => return Err(MemoryError::OffsetTooLarge),
219247
Some(new_off) if new_off >= i64::MAX as u64 => {

src/vmm/src/vstate/vm.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ use std::os::fd::FromRawFd;
1212
use std::path::Path;
1313
use std::sync::Arc;
1414

15-
use kvm_bindings::{kvm_create_guest_memfd, kvm_userspace_memory_region, kvm_userspace_memory_region2, KVM_MEM_LOG_DIRTY_PAGES};
15+
use kvm_bindings::{
16+
KVM_MEM_LOG_DIRTY_PAGES, kvm_create_guest_memfd, kvm_userspace_memory_region,
17+
kvm_userspace_memory_region2,
18+
};
1619
use kvm_ioctls::{Cap, VmFd};
1720
use vmm_sys_util::eventfd::EventFd;
1821

tests/integration_tests/functional/test_api.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -375,9 +375,7 @@ def test_api_machine_config(uvm_plain):
375375
bad_size = (1 << 64) - 1
376376
test_microvm.api.machine_config.patch(mem_size_mib=bad_size)
377377

378-
fail_msg = re.escape(
379-
"Invalid Memory Configuration: Cannot create mmap region: Out of memory (os error 12)"
380-
)
378+
fail_msg = re.escape("Out of memory (os error 12)")
381379
with pytest.raises(RuntimeError, match=fail_msg):
382380
test_microvm.start()
383381

0 commit comments

Comments
 (0)