Skip to content

Commit 747658f

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 <168595099+syntactically@users.noreply.github.com>
1 parent 85659be commit 747658f

File tree

4 files changed

+69
-27
lines changed

4 files changed

+69
-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: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,9 @@ fn load_wasm_module_phys(function_call: &FunctionCall) -> Result<Vec<u8>> {
107107

108108
#[no_mangle]
109109
pub extern "C" fn hyperlight_main() {
110+
crate::platform::register_page_fault_handler();
111+
110112
let mut config = Config::new();
111-
config.memory_reservation(0);
112-
config.memory_guard_size(0);
113-
config.memory_reservation_for_growth(0);
114-
config.guard_before_linear_memory(false);
115113
config.with_custom_code_memory(Some(alloc::sync::Arc::new(
116114
crate::platform::WasmtimeCodeMemory {},
117115
)));

src/wasm_runtime/src/module.rs

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

9191
fn init_wasm_runtime() -> Result<Vec<u8>> {
9292
let mut config = Config::new();
93-
config.memory_reservation(0);
94-
config.memory_guard_size(0);
95-
config.memory_reservation_for_growth(0);
96-
config.guard_before_linear_memory(false);
9793
config.with_custom_code_memory(Some(alloc::sync::Arc::new(
9894
crate::platform::WasmtimeCodeMemory {},
9995
)));
@@ -171,6 +167,8 @@ fn load_wasm_module_phys(function_call: &FunctionCall) -> Result<Vec<u8>> {
171167
#[no_mangle]
172168
#[allow(clippy::fn_to_numeric_cast)] // GuestFunctionDefinition expects a function pointer as i64
173169
pub extern "C" fn hyperlight_main() {
170+
crate::platform::register_page_fault_handler();
171+
174172
register_function(GuestFunctionDefinition::new(
175173
"PrintOutput".to_string(),
176174
vec![ParameterType::String],

src/wasm_runtime/src/platform.rs

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,90 @@ 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::sync::atomic::{AtomicPtr, AtomicU64, Ordering};
2019

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

2364
// Wasmtime Embedding Interface
2465

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

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

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

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

0 commit comments

Comments
 (0)