From c185c751bdfe6ac315be834b810336f7a5bed756 Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Thu, 23 Sep 2021 16:26:12 -0400 Subject: [PATCH] feat: -1 on wasm memory.grow instruction failure --- runtime/include/runtime.h | 2 +- runtime/src/memory/64bit_nix.c | 73 +++++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/runtime/include/runtime.h b/runtime/include/runtime.h index 0a07045..bbb8a0d 100644 --- a/runtime/include/runtime.h +++ b/runtime/include/runtime.h @@ -40,7 +40,7 @@ extern void runtime_set_resource_limits_to_max(void); /* External Symbols */ extern void alloc_linear_memory(void); -extern void expand_memory(void); +extern int expand_memory(void); INLINE char *get_function_from_table(uint32_t idx, uint32_t type_id); INLINE char *get_memory_ptr_for_runtime(uint32_t offset, uint32_t bounds_check); extern void stub_init(int32_t offset); diff --git a/runtime/src/memory/64bit_nix.c b/runtime/src/memory/64bit_nix.c index ef1e5ef..b98ffdc 100644 --- a/runtime/src/memory/64bit_nix.c +++ b/runtime/src/memory/64bit_nix.c @@ -6,24 +6,36 @@ #include -void +/** + * @brief Expand the linear memory of the active WebAssembly sandbox by a single page + * + * @return int + */ +int expand_memory(void) { struct sandbox *sandbox = current_sandbox_get(); assert(sandbox->state == SANDBOX_RUNNING); + assert(local_sandbox_context_cache.memory.size % WASM_PAGE_SIZE == 0); - // TODO: Refactor to return RC signifying out-of-mem to caller. Issue #96. - if (local_sandbox_context_cache.memory.size + WASM_PAGE_SIZE >= local_sandbox_context_cache.memory.max) - panic("expand_memory - Out of Memory!. %u out of %lu\n", local_sandbox_context_cache.memory.size, - local_sandbox_context_cache.memory.max); + /* Return -1 if we've hit the linear memory max */ + if (unlikely(local_sandbox_context_cache.memory.size + WASM_PAGE_SIZE + >= local_sandbox_context_cache.memory.max)) { + debuglog("expand_memory - Out of Memory!. %u out of %lu\n", local_sandbox_context_cache.memory.size, + local_sandbox_context_cache.memory.max); + return -1; + } // Remap the relevant wasm page to readable char *mem_as_chars = local_sandbox_context_cache.memory.start; char *page_address = &mem_as_chars[local_sandbox_context_cache.memory.size]; void *map_result = mmap(page_address, WASM_PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); - if (map_result == MAP_FAILED) panic("Mapping of new memory failed"); + if (map_result == MAP_FAILED) { + debuglog("Mapping of new memory failed"); + return -1; + } local_sandbox_context_cache.memory.size += WASM_PAGE_SIZE; @@ -38,6 +50,7 @@ expand_memory(void) // local_sandbox_context_cache is "forked state", so update authoritative member sandbox->memory.size = local_sandbox_context_cache.memory.size; + return 0; } INLINE char * @@ -54,3 +67,51 @@ get_memory_ptr_for_runtime(uint32_t offset, uint32_t bounds_check) return address; } + +/** + * @brief Stub that implements the WebAssembly memory.grow instruction + * + * @param count number of pages to grow the WebAssembly linear memory by + * @return The previous size of the linear memory in pages or -1 if enough memory cannot be allocated + */ +int32_t +instruction_memory_grow(uint32_t count) +{ + int rc = local_sandbox_context_cache.memory.size / WASM_PAGE_SIZE; + + for (int i = 0; i < count; i++) { + if (unlikely(expand_memory() != 0)) { + rc = -1; + break; + } + } + + return rc; +} + +/* + * Table handling functionality + * This was moved from compiletime in order to place the + * function in the callstack in GDB. It can be moved back + * to runtime/compiletime/memory/64bit_nix.c to remove the + * additional function call + */ +char * +get_function_from_table(uint32_t idx, uint32_t type_id) +{ +#ifdef LOG_FUNCTION_TABLE + fprintf(stderr, "get_function_from_table(idx: %u, type_id: %u)\n", idx, type_id); + fprintf(stderr, "indirect_table_size: %u\n", INDIRECT_TABLE_SIZE); +#endif + assert(idx < INDIRECT_TABLE_SIZE); + + struct indirect_table_entry f = local_sandbox_context_cache.module_indirect_table[idx]; +#ifdef LOG_FUNCTION_TABLE + fprintf(stderr, "assumed type: %u, type in table: %u\n", type_id, f.type_id); +#endif + assert(f.type_id == type_id); + + assert(f.func_pointer != NULL); + + return f.func_pointer; +}