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
#define STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT 3
static os_thread_local_attribute WASMExecEnv *aot_exec_env = NULL;
static inline uint8 *
@ -567,6 +569,7 @@ aot_signal_handler(void *sig_addr)
uint8 *mapped_mem_start_addr, *mapped_mem_end_addr;
uint8 *stack_min_addr;
uint32 page_size;
uint32 guard_page_count = STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT;
/* Check whether current thread is running aot function */
if (aot_exec_env
@ -591,7 +594,8 @@ aot_signal_handler(void *sig_addr)
os_longjmp(jmpbuf_node->jmpbuf, 1);
}
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
native thread's guard page */
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;
while (1) {
uint8 *touch_addr = os_alloca(page_size / 2);
sum += *touch_addr;
volatile uint8 *touch_addr =
(volatile uint8*)os_alloca(page_size / 2);
if (touch_addr < stack_min_addr + page_size) {
sum += *(stack_min_addr + page_size - 1);
break;
}
sum += *touch_addr;
}
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;
WASMJmpBuf *jmpbuf_node, *jmpbuf_node_pop;
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);
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
&& (aot_exec_env != 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. */
touch_pages(stack_min_addr, page_size);
/* 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.");
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) {
ret = wasm_runtime_invoke_native(exec_env, func_ptr, func_type,
signature, attachment,
argv, argc, argv);
argv, argc, argv_ret);
}
else {
/* 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);
if (!exec_env->jmpbuf_stack_top) {
/* 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);
*p_aot_exec_env = NULL;
}
@ -1113,6 +1130,19 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
void *attachment;
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);
import_func = aot_module->import_funcs + func_idx;

View File

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