Enhance the native stack overflow check (#302)

This commit is contained in:
wenyongh 2020-07-07 09:56:46 +08:00 committed by GitHub
parent 9b8fc6ae95
commit 2fc7230009
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 9 deletions

View File

@ -550,6 +550,8 @@ aot_lookup_function(const AOTModuleInstance *module_inst,
#ifdef OS_ENABLE_HW_BOUND_CHECK #ifdef OS_ENABLE_HW_BOUND_CHECK
#define STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT 3
static os_thread_local_attribute WASMExecEnv *aot_exec_env = NULL; static os_thread_local_attribute WASMExecEnv *aot_exec_env = NULL;
static inline uint8 * static inline uint8 *
@ -567,6 +569,7 @@ aot_signal_handler(void *sig_addr)
uint8 *mapped_mem_start_addr, *mapped_mem_end_addr; uint8 *mapped_mem_start_addr, *mapped_mem_end_addr;
uint8 *stack_min_addr; uint8 *stack_min_addr;
uint32 page_size; uint32 page_size;
uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
/* Check whether current thread is running aot function */ /* Check whether current thread is running aot function */
if (aot_exec_env if (aot_exec_env
@ -591,7 +594,8 @@ aot_signal_handler(void *sig_addr)
os_longjmp(jmpbuf_node->jmpbuf, 1); os_longjmp(jmpbuf_node->jmpbuf, 1);
} }
else if (stack_min_addr - page_size <= (uint8*)sig_addr else if (stack_min_addr - page_size <= (uint8*)sig_addr
&& (uint8*)sig_addr < stack_min_addr + page_size * 3) { && (uint8*)sig_addr < stack_min_addr
+ page_size * guard_page_count) {
/* The address which causes segmentation fault is inside /* The address which causes segmentation fault is inside
native thread's guard page */ native thread's guard page */
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW); aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
@ -621,11 +625,13 @@ touch_pages(uint8 *stack_min_addr, uint32 page_size)
{ {
uint8 sum = 0; uint8 sum = 0;
while (1) { while (1) {
uint8 *touch_addr = os_alloca(page_size / 2); volatile uint8 *touch_addr =
sum += *touch_addr; (volatile uint8*)os_alloca(page_size / 2);
if (touch_addr < stack_min_addr + page_size) { if (touch_addr < stack_min_addr + page_size) {
sum += *(stack_min_addr + page_size - 1);
break; break;
} }
sum += *touch_addr;
} }
return sum; return sum;
} }
@ -640,9 +646,19 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
WASMExecEnv **p_aot_exec_env = &aot_exec_env; WASMExecEnv **p_aot_exec_env = &aot_exec_env;
WASMJmpBuf *jmpbuf_node, *jmpbuf_node_pop; WASMJmpBuf *jmpbuf_node, *jmpbuf_node_pop;
uint32 page_size = os_getpagesize(); uint32 page_size = os_getpagesize();
uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
uint8 *stack_min_addr = get_stack_min_addr(exec_env, page_size); uint8 *stack_min_addr = get_stack_min_addr(exec_env, page_size);
bool ret; bool ret;
/* Check native stack overflow firstly to ensure we have enough
native stack to run the following codes before actually calling
the aot function in invokeNative function. */
if ((uint8*)&module_inst < exec_env->native_stack_boundary
+ page_size * (guard_page_count + 1)) {
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
return false;
}
if (aot_exec_env if (aot_exec_env
&& (aot_exec_env != exec_env)) { && (aot_exec_env != exec_env)) {
aot_set_exception(module_inst, "Invalid exec env."); aot_set_exception(module_inst, "Invalid exec env.");
@ -654,7 +670,8 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
lazily grow the stack mapping as a guard page is hit. */ lazily grow the stack mapping as a guard page is hit. */
touch_pages(stack_min_addr, page_size); touch_pages(stack_min_addr, page_size);
/* First time to call aot function, protect one page */ /* First time to call aot function, protect one page */
if (os_mprotect(stack_min_addr, page_size * 3, MMAP_PROT_NONE) != 0) { if (os_mprotect(stack_min_addr, page_size * guard_page_count,
MMAP_PROT_NONE) != 0) {
aot_set_exception(module_inst, "Set protected page failed."); aot_set_exception(module_inst, "Set protected page failed.");
return false; return false;
} }
@ -671,7 +688,7 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
if (os_setjmp(jmpbuf_node->jmpbuf) == 0) { if (os_setjmp(jmpbuf_node->jmpbuf) == 0) {
ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type, ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type,
signature, attachment, signature, attachment,
argv, argc, argv); argv, argc, argv_ret);
} }
else { else {
/* Exception has been set in signal handler before calling longjmp */ /* Exception has been set in signal handler before calling longjmp */
@ -683,7 +700,7 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
wasm_runtime_free(jmpbuf_node); wasm_runtime_free(jmpbuf_node);
if (!exec_env->jmpbuf_stack_top) { if (!exec_env->jmpbuf_stack_top) {
/* Unprotect the guard page when the nested call depth is zero */ /* Unprotect the guard page when the nested call depth is zero */
os_mprotect(stack_min_addr, page_size * 3, os_mprotect(stack_min_addr, page_size * guard_page_count,
MMAP_PROT_READ | MMAP_PROT_WRITE); MMAP_PROT_READ | MMAP_PROT_WRITE);
*p_aot_exec_env = NULL; *p_aot_exec_env = NULL;
} }
@ -1113,6 +1130,19 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
void *attachment; void *attachment;
char buf[128]; char buf[128];
#ifdef OS_ENABLE_HW_BOUND_CHECK
uint32 page_size = os_getpagesize();
uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
/* Check native stack overflow firstly to ensure we have enough
native stack to run the following codes before actually calling
the aot function in invokeNative function. */
if ((uint8*)&module_inst < exec_env->native_stack_boundary
+ page_size * (guard_page_count + 1)) {
aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
return false;
}
#endif
bh_assert(func_idx < aot_module->import_func_count); bh_assert(func_idx < aot_module->import_func_count);
import_func = aot_module->import_funcs + func_idx; import_func = aot_module->import_funcs + func_idx;

View File

@ -2797,6 +2797,10 @@ fail:
return ret; return ret;
} }
#endif /* end of defined(BUILD_TARGET_X86_64) \
|| defined(BUILD_TARGET_AMD_64) \
|| defined(BUILD_TARGET_AARCH64) */
bool bool
wasm_runtime_call_indirect(WASMExecEnv *exec_env, wasm_runtime_call_indirect(WASMExecEnv *exec_env,
uint32_t element_indices, uint32_t element_indices,
@ -2825,6 +2829,3 @@ wasm_runtime_call_indirect(WASMExecEnv *exec_env,
return false; return false;
} }
#endif /* end of defined(BUILD_TARGET_X86_64) \
|| defined(BUILD_TARGET_AMD_64) \
|| defined(BUILD_TARGET_AARCH64) */