Skip to content

Commit 54f63d0

Browse files
committed
Run shared memory tests with miri
Signed-off-by: Ludvig Liljenberg <4257730+ludfjig@users.noreply.github.com>
1 parent 6b28b76 commit 54f63d0

4 files changed

Lines changed: 57 additions & 44 deletions

File tree

Justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,9 @@ test-doc target=default-target features="":
212212

213213
miri-tests:
214214
rustup +nightly component list | grep -q "miri.*installed" || rustup component add miri --toolchain nightly
215-
# For now only run miri tests on hyperlight-common with trace_guest feature
216215
# We can add more as needed
217216
cargo +nightly miri test -p hyperlight-common -F trace_guest
217+
cargo +nightly miri test -p hyperlight-host --lib -- mem::shared_mem::tests
218218

219219
################
220220
### LINTING ####

src/hyperlight_host/src/mem/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ pub mod ptr_offset;
3535
/// A wrapper around unsafe functionality to create and initialize
3636
/// a memory region for a guest running in a sandbox.
3737
pub mod shared_mem;
38-
/// Utilities for writing shared memory tests
39-
#[cfg(test)]
38+
/// Utilities for writing shared memory
39+
#[cfg(all(test, not(miri)))] // uses proptest which isn't miri-compatible
4040
pub(crate) mod shared_mem_tests;

src/hyperlight_host/src/mem/shared_mem.rs

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use crate::HyperlightError::SnapshotSizeMismatch;
4141
#[cfg(target_os = "windows")]
4242
use crate::HyperlightError::{MemoryRequestTooBig, WindowsAPIError};
4343
use crate::sandbox::snapshot::Snapshot;
44-
use crate::{Result, log_then_return, new_error};
44+
use crate::{HyperlightError, Result, log_then_return, new_error};
4545

4646
/// Makes sure that the given `offset` and `size` are within the bounds of the memory with size `mem_size`.
4747
macro_rules! bounds_check {
@@ -312,12 +312,11 @@ impl ExclusiveSharedMemory {
312312
#[cfg(target_os = "linux")]
313313
#[instrument(skip_all, parent = Span::current(), level= "Trace")]
314314
pub fn new(min_size_bytes: usize) -> Result<Self> {
315-
use libc::{
316-
MAP_ANONYMOUS, MAP_FAILED, MAP_NORESERVE, MAP_SHARED, PROT_NONE, PROT_READ, PROT_WRITE,
317-
c_int, mmap, mprotect, off_t, size_t,
318-
};
319-
320-
use crate::error::HyperlightError::{MemoryRequestTooBig, MmapFailed, MprotectFailed};
315+
#[cfg(miri)]
316+
use libc::MAP_PRIVATE;
317+
use libc::{MAP_ANONYMOUS, MAP_FAILED, PROT_READ, PROT_WRITE, c_int, mmap, off_t, size_t};
318+
#[cfg(not(miri))]
319+
use libc::{MAP_NORESERVE, MAP_SHARED, PROT_NONE, mprotect};
321320

322321
if min_size_bytes == 0 {
323322
return Err(new_error!("Cannot create shared memory with size 0"));
@@ -337,39 +336,55 @@ impl ExclusiveSharedMemory {
337336
// usize and isize are guaranteed to be the same size, and
338337
// isize::MAX should be positive, so this cast should be safe.
339338
if total_size > isize::MAX as usize {
340-
return Err(MemoryRequestTooBig(total_size, isize::MAX as usize));
339+
return Err(HyperlightError::MemoryRequestTooBig(
340+
total_size,
341+
isize::MAX as usize,
342+
));
341343
}
342344

343345
// allocate the memory
346+
#[cfg(not(miri))]
347+
let flags = MAP_ANONYMOUS | MAP_SHARED | MAP_NORESERVE;
348+
#[cfg(miri)]
349+
let flags = MAP_ANONYMOUS | MAP_PRIVATE;
350+
344351
let addr = unsafe {
345352
mmap(
346353
null_mut(),
347354
total_size as size_t,
348355
PROT_READ | PROT_WRITE,
349-
MAP_ANONYMOUS | MAP_SHARED | MAP_NORESERVE,
356+
flags,
350357
-1 as c_int,
351358
0 as off_t,
352359
)
353360
};
354361
if addr == MAP_FAILED {
355-
log_then_return!(MmapFailed(Error::last_os_error().raw_os_error()));
362+
log_then_return!(HyperlightError::MmapFailed(
363+
Error::last_os_error().raw_os_error()
364+
));
356365
}
357366

358367
// protect the guard pages
359-
360-
let res = unsafe { mprotect(addr, PAGE_SIZE_USIZE, PROT_NONE) };
361-
if res != 0 {
362-
return Err(MprotectFailed(Error::last_os_error().raw_os_error()));
363-
}
364-
let res = unsafe {
365-
mprotect(
366-
(addr as *const u8).add(total_size - PAGE_SIZE_USIZE) as *mut c_void,
367-
PAGE_SIZE_USIZE,
368-
PROT_NONE,
369-
)
370-
};
371-
if res != 0 {
372-
return Err(MprotectFailed(Error::last_os_error().raw_os_error()));
368+
#[cfg(not(miri))]
369+
{
370+
let res = unsafe { mprotect(addr, PAGE_SIZE_USIZE, PROT_NONE) };
371+
if res != 0 {
372+
return Err(HyperlightError::MprotectFailed(
373+
Error::last_os_error().raw_os_error(),
374+
));
375+
}
376+
let res = unsafe {
377+
mprotect(
378+
(addr as *const u8).add(total_size - PAGE_SIZE_USIZE) as *mut c_void,
379+
PAGE_SIZE_USIZE,
380+
PROT_NONE,
381+
)
382+
};
383+
if res != 0 {
384+
return Err(HyperlightError::MprotectFailed(
385+
Error::last_os_error().raw_os_error(),
386+
));
387+
}
373388
}
374389

375390
Ok(Self {
@@ -646,7 +661,7 @@ pub trait SharedMemory {
646661
/// not need to be marked as `unsafe` because doing anything with
647662
/// this pointer itself requires `unsafe`.
648663
fn base_ptr(&self) -> *mut u8 {
649-
self.base_addr() as *mut u8
664+
self.region().ptr.wrapping_add(PAGE_SIZE_USIZE)
650665
}
651666

652667
/// Return the length of usable memory contained in `self`.
@@ -965,10 +980,14 @@ impl SharedMemory for HostSharedMemory {
965980
#[cfg(test)]
966981
mod tests {
967982
use hyperlight_common::mem::PAGE_SIZE_USIZE;
983+
#[cfg(not(miri))]
968984
use proptest::prelude::*;
969985

970-
use super::{ExclusiveSharedMemory, HostSharedMemory, SharedMemory};
986+
#[cfg(not(miri))]
987+
use super::HostSharedMemory;
988+
use super::{ExclusiveSharedMemory, SharedMemory};
971989
use crate::Result;
990+
#[cfg(not(miri))]
972991
use crate::mem::shared_mem_tests::read_write_test_suite;
973992

974993
#[test]
@@ -1059,6 +1078,8 @@ mod tests {
10591078
Ok(())
10601079
}
10611080

1081+
// proptest uses file I/O (getcwd, open) which miri doesn't support
1082+
#[cfg(not(miri))]
10621083
proptest! {
10631084
#[test]
10641085
fn read_write_i32(val in -0x1000_i32..0x1000_i32) {
@@ -1238,6 +1259,7 @@ mod tests {
12381259

12391260
// provides a way for running the above tests in a separate process since they expect to crash
12401261
#[test]
1262+
#[cfg_attr(miri, ignore)] // miri can't spawn subprocesses
12411263
fn guard_page_testing_shim() {
12421264
let tests = vec!["read", "write", "exec"];
12431265
for test in tests {

src/tests/rust_guests/simpleguest/Cargo.lock

Lines changed: 6 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)