Skip to content
This repository was archived by the owner on Mar 24, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
b64ee49
Improved approach.
fst-crenshaw Mar 23, 2020
2160f4e
Do not make the heap size larger than the slot size limit.
fst-crenshaw Mar 24, 2020
e361aec
Added a test to affirm that an oversized heap memory size limit is re…
fst-crenshaw Mar 24, 2020
85ef2c8
Initializing heap_memory_size with a more sensible value.
fst-crenshaw Mar 24, 2020
cb2270b
Fmt
fst-crenshaw Mar 25, 2020
df004c8
Remove silly comment.
fst-crenshaw Mar 25, 2020
13284c4
Merge branch 'master' into tlc/issue-451-b
fst-crenshaw Mar 25, 2020
252b9b5
Address PR comments
fst-crenshaw Mar 25, 2020
42e9884
Address PR comments
fst-crenshaw Mar 25, 2020
e313821
Address PR comments.
fst-crenshaw Mar 25, 2020
cfb324f
Address PR comments.
fst-crenshaw Mar 25, 2020
64ce8b0
Use match
fst-crenshaw Mar 26, 2020
7c95d26
Address PR comments.
fst-crenshaw Mar 26, 2020
0216cdf
Make diff smaller.
fst-crenshaw Mar 26, 2020
c97049d
Make diff smaller.
fst-crenshaw Mar 26, 2020
ba3196a
Test is failing. Should it?
fst-crenshaw Mar 26, 2020
c153558
Ok.
fst-crenshaw Mar 27, 2020
f7fb508
Remove silly.
fst-crenshaw Mar 27, 2020
7f19446
Fixed broken test.
fst-crenshaw Mar 27, 2020
0902b82
Fmt.
fst-crenshaw Mar 27, 2020
0073db0
Passing all new tests.
fst-crenshaw Mar 27, 2020
424ecdb
Fmt.
fst-crenshaw Mar 27, 2020
7da7a4e
Address PR comments.
fst-crenshaw Mar 27, 2020
7b40d12
Fmt.
fst-crenshaw Mar 27, 2020
3dd8eed
Add test for the mundane and the successful.
fst-crenshaw Mar 31, 2020
addc0db
Passing all tests. The HeapSpec has an expectation of size. The ins…
fst-crenshaw Mar 31, 2020
7996b40
Passing all tests. The HeapSpec has an expectation of size. The ins…
fst-crenshaw Mar 31, 2020
fbb25f6
Make the test less ughy.
fst-crenshaw Mar 31, 2020
0e5aed7
Update lucet-runtime/lucet-runtime-internals/src/alloc/tests.rs
fst-crenshaw Mar 31, 2020
4a9acdf
Update lucet-runtime/lucet-runtime-internals/src/alloc/tests.rs
fst-crenshaw Mar 31, 2020
d396192
Update lucet-runtime/lucet-runtime-internals/src/alloc/tests.rs
fst-crenshaw Apr 1, 2020
cd7b90f
Merge branch 'master' into tlc/issue-451-b
fst-crenshaw Apr 2, 2020
a9ac3a2
Be more clear about with_heap_size docs.
fst-crenshaw Apr 2, 2020
5d76141
The usual fussing over words.
fst-crenshaw Apr 2, 2020
c104991
Mmmaybe.
fst-crenshaw Apr 2, 2020
4e98ba4
Mmmaybe.
fst-crenshaw Apr 2, 2020
44bc0b0
Mmmaybe.
fst-crenshaw Apr 2, 2020
2ebec05
Fix spelling mistakes
fst-crenshaw Apr 2, 2020
b0c5ee4
Merge branch 'master' into tlc/issue-451-b
fst-crenshaw Apr 6, 2020
6601211
Merge branch 'master' into tlc/issue-451-b
fst-crenshaw Apr 6, 2020
72780f1
But it is just so ugly.
fst-crenshaw Apr 6, 2020
c550696
Fmt.
fst-crenshaw Apr 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lucet-runtime/lucet-runtime-internals/src/alloc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ impl Slot {
pub struct Alloc {
pub heap_accessible_size: usize,
pub heap_inaccessible_size: usize,
pub heap_memory_size_limit: usize,
pub slot: Option<Slot>,
pub region: Arc<dyn RegionInternal>,
}
Expand Down Expand Up @@ -241,7 +242,7 @@ impl Alloc {
}
// The runtime sets a limit on how much of the heap can be backed by real memory. Don't let
// the heap expand beyond that:
if self.heap_accessible_size + expand_pagealigned as usize > slot.limits.heap_memory_size {
if self.heap_accessible_size + expand_pagealigned as usize > self.heap_memory_size_limit {
bail_limits_exceeded!(
"expansion would exceed runtime-specified heap limit: {:?}",
slot.limits
Expand Down Expand Up @@ -396,7 +397,7 @@ impl Alloc {
/// Runtime limits for the various memories that back a Lucet instance.
///
/// Each value is specified in bytes, and must be evenly divisible by the host page size (4K).
#[derive(Clone, Debug)]
#[derive(Clone, Copy, Debug)]
#[repr(C)]
pub struct Limits {
/// Max size of the heap, which can be backed by real memory. (default 1M)
Expand Down
124 changes: 124 additions & 0 deletions lucet-runtime/lucet-runtime-internals/src/alloc/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,46 @@ macro_rules! alloc_tests {
assert_eq!(heap[new_heap_len - 1], 0xFF);
}

/// This test exercises custom limits on the heap_memory_size.
/// In this scenario, the Region has a limit on the heap memory
/// size, but the instance has a smaller limit. Attempts to expand
/// the heap fail, but the existing heap can still be used.
#[test]
fn expand_past_spec_max_with_custom_limit() {
let region = TestRegion::create(10, &LIMITS).expect("region created");
let module = MockModuleBuilder::new()
.with_heap_spec(THREE_PAGE_MAX_HEAP)
.build();
let mut inst = region
.new_instance_builder(module.clone())
.with_heap_size_limit((THREEPAGE_INITIAL_SIZE) as usize)
.build()
.expect("new_instance succeeds");

let heap_len = inst.alloc().heap_len();
assert_eq!(heap_len, THREEPAGE_INITIAL_SIZE as usize);

// Expand the heap within the Region limit but past the
// instance limit.
let new_heap_area = inst.alloc_mut().expand_heap(
(THREEPAGE_MAX_SIZE - THREEPAGE_INITIAL_SIZE) as u32,
module.as_ref(),
);
assert!(
new_heap_area.is_err(),
"heap expansion past instance limit fails"
);

// Affirm that the existing heap can still be used.
let new_heap_len = inst.alloc().heap_len();
assert_eq!(new_heap_len, heap_len);

let heap = unsafe { inst.alloc_mut().heap_mut() };
assert_eq!(heap[new_heap_len - 1], 0);
heap[new_heap_len - 1] = 0xFF;
assert_eq!(heap[new_heap_len - 1], 0xFF);
}

const EXPANDPASTLIMIT_INITIAL_SIZE: u64 = LIMITS_HEAP_MEM_SIZE as u64 - (64 * 1024);
const EXPANDPASTLIMIT_MAX_SIZE: u64 = LIMITS_HEAP_MEM_SIZE as u64 + (64 * 1024);
const EXPAND_PAST_LIMIT_SPEC: HeapSpec = HeapSpec {
Expand Down Expand Up @@ -836,6 +876,90 @@ macro_rules! alloc_tests {
Ok(_) => panic!("unexpected success"),
}
}

/// This test exercises custom limits on the heap_memory_size.
/// In this scenario, the Region has a limit on the heap
/// memory size, but the instance has a larger limit. An
/// instance's custom limit must not exceed the Region's.
#[test]
fn reject_heap_memory_size_exceeds_region_limits() {
let region = TestRegion::create(1, &LIMITS).expect("region created");
let module = MockModuleBuilder::new()
.with_heap_spec(THREE_PAGE_MAX_HEAP)
.build();
let res = region
.new_instance_builder(module.clone())
.with_heap_size_limit(&LIMITS.heap_memory_size * 2)
.build();

match res {
Err(Error::InvalidArgument(
"heap memory size requested for instance is larger than slot allows",
)) => (),
Err(e) => panic!("unexpected error: {}", e),
Ok(_) => panic!("unexpected success"),
}
}

/// This test exercises custom limits on the heap_memory_size.
/// In this scenario, successfully create a custom-sized
/// instance, drop it, then create a default-sized instance to
/// affirm that a custom size doesn't somehow overwrite the
/// default size.
#[test]
fn custom_size_does_not_break_default() {
let region = TestRegion::create(1, &LIMITS).expect("region created");

// Build an instance that is has custom limits that are big
// enough to accommodate the HeapSpec.
let custom_inst = region
.new_instance_builder(
MockModuleBuilder::new()
.with_heap_spec(THREE_PAGE_MAX_HEAP)
.build(),
)
.with_heap_size_limit((THREE_PAGE_MAX_HEAP.initial_size * 2) as usize)
.build()
.expect("new instance succeeds");

// Affirm that its heap is the expected size, the size
// specified in the HeapSpec.
let heap_len = custom_inst.alloc().heap_len();
assert_eq!(heap_len, THREE_PAGE_MAX_HEAP.initial_size as usize);
drop(custom_inst);

// Build a default heap-limited instance, to make sure the
// custom limits didn't break the defaults.
let default_inst = region
.new_instance(
MockModuleBuilder::new()
.with_heap_spec(SMALL_GUARD_HEAP)
.build(),
)
.expect("new_instance succeeds");

// Affirm that its heap is the expected size.
let heap_len = default_inst.alloc().heap_len();
assert_eq!(heap_len, SMALL_GUARD_HEAP.initial_size as usize);
}

/// This test exercises custom limits on the heap_memory_size.
/// In this scenario, the HeapSpec has an expectation for the
/// initial heap memory size, but the instance's limit is too small.
#[test]
fn reject_heap_memory_size_exeeds_instance_limits() {
let region = TestRegion::create(1, &LIMITS).expect("region created");
let res = region
.new_instance_builder(
MockModuleBuilder::new()
.with_heap_spec(THREE_PAGE_MAX_HEAP)
.build(),
)
.with_heap_size_limit((THREE_PAGE_MAX_HEAP.initial_size / 2) as usize)
.build();

assert!(res.is_err(), "new_instance fails");
}
};
}

Expand Down
15 changes: 14 additions & 1 deletion lucet-runtime/lucet-runtime-internals/src/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub trait RegionInternal: Send + Sync {
&self,
module: Arc<dyn Module>,
embed_ctx: CtxMap,
heap_memory_size_limit: usize,
) -> Result<InstanceHandle, Error>;

/// Unmaps the heap, stack, and globals of an `Alloc`, while retaining the virtual address
Expand Down Expand Up @@ -93,6 +94,7 @@ pub struct InstanceBuilder<'a> {
region: &'a dyn RegionInternal,
module: Arc<dyn Module>,
embed_ctx: CtxMap,
heap_memory_size_limit: usize,
}

impl<'a> InstanceBuilder<'a> {
Expand All @@ -101,9 +103,19 @@ impl<'a> InstanceBuilder<'a> {
region,
module,
embed_ctx: CtxMap::default(),
heap_memory_size_limit: region.get_limits().heap_memory_size,
}
}

/// Add a smaller, custom limit for the heap memory size to the built instance.
///
/// This call is optional. Attempts to build a new instance fail if the
/// limit supplied by with_heap_size_limit() exceeds that of the region.
pub fn with_heap_size_limit(mut self, heap_memory_size_limit: usize) -> Self {
self.heap_memory_size_limit = heap_memory_size_limit;
self
}

/// Add an embedder context to the built instance.
///
/// Up to one context value of any particular type may exist in the instance. If a context value
Expand All @@ -120,6 +132,7 @@ impl<'a> InstanceBuilder<'a> {
/// This function runs the guest code for the WebAssembly `start` section, and running any guest
/// code is potentially unsafe; see [`Instance::run()`](struct.Instance.html#method.run).
pub fn build(self) -> Result<InstanceHandle, Error> {
self.region.new_instance_with(self.module, self.embed_ctx)
self.region
.new_instance_with(self.module, self.embed_ctx, self.heap_memory_size_limit)
}
}
27 changes: 25 additions & 2 deletions lucet-runtime/lucet-runtime-internals/src/region/mmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use libc::c_void;
#[cfg(not(target_os = "linux"))]
use libc::memset;
use nix::sys::mman::{madvise, mmap, munmap, MapFlags, MmapAdvise, ProtFlags};
use std::cmp::Ordering;
use std::ptr;
use std::sync::{Arc, RwLock, Weak};

Expand Down Expand Up @@ -78,11 +79,32 @@ impl RegionInternal for MmapRegion {
&self,
module: Arc<dyn Module>,
embed_ctx: CtxMap,
heap_memory_size_limit: usize,
) -> Result<InstanceHandle, Error> {
let custom_limits;
let mut limits = self.get_limits();

// Affirm that the module, if instantiated, would not violate
// any runtime memory limits.
let limits = self.get_limits();
module.validate_runtime_spec(limits)?;
match heap_memory_size_limit.cmp(&limits.heap_memory_size) {
Ordering::Less => {
// The supplied heap_memory_size is smaller than
// default. Augment the limits with this custom value
// so that it may be validated.
custom_limits = Limits {
heap_memory_size: heap_memory_size_limit,
..*limits
};
limits = &custom_limits;
}
Ordering::Equal => (),
Ordering::Greater => {
return Err(Error::InvalidArgument(
"heap memory size requested for instance is larger than slot allows",
))
}
}
module.validate_runtime_spec(&limits)?;

let slot = self
.freelist
Expand Down Expand Up @@ -127,6 +149,7 @@ impl RegionInternal for MmapRegion {
let alloc = Alloc {
heap_accessible_size: 0, // the `reset` call in `new_instance_handle` will set this
heap_inaccessible_size: slot.limits.heap_address_space_size,
heap_memory_size_limit,
slot: Some(slot),
region,
};
Expand Down