Skip to content

Commit 2a168d1

Browse files
committed
Begin to enable virtual memory in wasmtime
There is a big caveat here, which is that wasmtime's mprotect calls are ignored, so this sandbox is very unsound: a wasm module can take over the entire guest easily Signed-off-by: Lucy Menon <[email protected]>
1 parent 3b2330b commit 2a168d1

File tree

4 files changed

+65
-27
lines changed

4 files changed

+65
-27
lines changed

src/hyperlight_wasm_aot/src/main.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,5 @@ fn main() {
150150
fn get_config() -> Config {
151151
let mut config = Config::new();
152152
config.target("x86_64-unknown-none").unwrap();
153-
config.memory_reservation(0);
154-
config.memory_reservation_for_growth(0);
155-
config.memory_guard_size(0);
156-
config.guard_before_linear_memory(false);
157153
config
158154
}

src/wasm_runtime/src/component.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,6 @@ pub extern "C" fn hyperlight_main() {
102102
platform::register_page_fault_handler();
103103

104104
let mut config = Config::new();
105-
config.memory_reservation(0);
106-
config.memory_guard_size(0);
107-
config.memory_reservation_for_growth(0);
108-
config.guard_before_linear_memory(false);
109105
config.with_custom_code_memory(Some(alloc::sync::Arc::new(platform::WasmtimeCodeMemory {})));
110106
let engine = Engine::new(&config).unwrap();
111107
let linker = Linker::new(&engine);

src/wasm_runtime/src/module.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,6 @@ pub fn guest_dispatch_function(function_call: &FunctionCall) -> Result<Vec<u8>>
8989

9090
fn init_wasm_runtime() -> Result<Vec<u8>> {
9191
let mut config = Config::new();
92-
config.memory_reservation(0);
93-
config.memory_guard_size(0);
94-
config.memory_reservation_for_growth(0);
95-
config.guard_before_linear_memory(false);
9692
config.with_custom_code_memory(Some(alloc::sync::Arc::new(platform::WasmtimeCodeMemory {})));
9793
let engine = Engine::new(&config)?;
9894
let mut linker = Linker::new(&engine);

src/wasm_runtime/src/platform.rs

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,41 +14,91 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
use alloc::alloc::{alloc, dealloc, Layout};
1817
use core::ffi::c_void;
1918
use core::ptr::NonNull;
2019
use core::sync::atomic::{AtomicPtr, AtomicU64, Ordering};
2120

2221
use hyperlight_guest_bin::exceptions::handler;
22+
use hyperlight_guest_bin::paging;
23+
24+
// Extremely stupid virtual address allocator
25+
// 0x1_0000_0000 is where the module is
26+
// we start at
27+
// 0x100_0000_0000 and go up from there
28+
static FIRST_VADDR: AtomicU64 = AtomicU64::new(0x100_0000_0000u64);
29+
fn page_fault_handler(
30+
_exception_number: u64,
31+
info: *mut handler::ExceptionInfo,
32+
_ctx: *mut handler::Context,
33+
page_fault_address: u64,
34+
) -> bool {
35+
let error_code = unsafe { (&raw const (*info).error_code).read_volatile() };
36+
// TODO: check if this is a guard-region trap (which can't happen
37+
// right now since we don't actually set the permissions properly
38+
// in mprotect)
39+
40+
// TODO: replace this with some generic virtual memory area data
41+
// structure in hyperlight core
42+
if (error_code & 0x1) == 0x0 && page_fault_address >= 0x100_0000_0000u64 {
43+
unsafe {
44+
let phys_page = paging::alloc_phys_pages(1);
45+
let virt_base = (page_fault_address & !0xFFF) as *mut u8;
46+
paging::map_region(
47+
phys_page,
48+
virt_base,
49+
hyperlight_guest_bin::OS_PAGE_SIZE as u64,
50+
);
51+
virt_base.write_bytes(0u8, hyperlight_guest_bin::OS_PAGE_SIZE as usize);
52+
}
53+
return true; // Try again!
54+
}
55+
false
56+
}
57+
pub(crate) fn register_page_fault_handler() {
58+
// On amd64, vector 14 is #PF
59+
// See AMD64 Architecture Programmer's Manual, Volume 2
60+
// §8.2 Vectors, p. 245
61+
// Table 8-1: Interrupt Vector Source and Cause
62+
handler::handlers[14].store(page_fault_handler as usize as u64, Ordering::Release);
63+
}
2364

2465
// Wasmtime Embedding Interface
2566

26-
/* We don't have proper support for lazy committing an mmap region, or
27-
* for setting up guard pages, because the guest doesn't have an *
28-
* appropriate interrupt handler yet. Consequently, we configure
29-
* wasmtime not to use any guard region, and precommit memory. */
67+
/* We don't actually have any sensible virtual memory areas, so
68+
* we just give out virtual addresses very coarsely with
69+
* probably-more-than-enough space between them, and take over
70+
* page-fault handling to hardcoded check if memory is in this region
71+
* (see above) */
3072
#[no_mangle]
31-
pub extern "C" fn wasmtime_mmap_new(size: usize, _prot_flags: u32, ret: &mut *mut u8) -> i32 {
32-
*ret = unsafe { alloc(Layout::from_size_align(size, 0x1000).unwrap()) };
73+
pub extern "C" fn wasmtime_mmap_new(_size: usize, _prot_flags: u32, ret: &mut *mut u8) -> i32 {
74+
if _size > 0x100_0000_0000 {
75+
panic!("wasmtime_mmap_{:x} {:x}", _size, _prot_flags);
76+
}
77+
*ret = FIRST_VADDR.fetch_add(0x100_0000_0000, Ordering::Relaxed) as *mut u8;
3378
0
3479
}
3580

36-
/* Because of the precommitted memory strategy, we can't generally
37-
* support remap */
81+
/* Remap is only used for changing the region size (which is presently
82+
* a no-op, since we just hand out very large regions and treat them all
83+
* the same), or possibly for changing permissions, which will be a no-op
84+
* as we don't properly implement permissions at the moment. */
3885
#[no_mangle]
3986
pub extern "C" fn wasmtime_mmap_remap(addr: *mut u8, size: usize, prot_flags: u32) -> i32 {
40-
panic!(
41-
"wasmtime_mmap_remap {:x} {:x} {:x}",
42-
addr as usize, size, prot_flags
43-
);
87+
if size > 0x100_0000_0000 {
88+
panic!(
89+
"wasmtime_mmap_remap {:x} {:x} {:x}",
90+
addr as usize, size, prot_flags
91+
);
92+
}
93+
0
4494
}
4595

4696
#[no_mangle]
47-
pub extern "C" fn wasmtime_munmap(ptr: *mut u8, size: usize) -> i32 {
48-
unsafe { dealloc(ptr, Layout::from_size_align(size, 0x1000).unwrap()) };
97+
pub extern "C" fn wasmtime_munmap(_ptr: *mut u8, _size: usize) -> i32 {
4998
0
5099
}
51100

101+
/* TODO: implement permissions properly */
52102
#[no_mangle]
53103
pub extern "C" fn wasmtime_mprotect(_ptr: *mut u8, _size: usize, prot_flags: u32) -> i32 {
54104
/* currently all memory is allocated RWX; we assume that

0 commit comments

Comments
 (0)