Fix repeatedly initialize shared memory data and protect the memory's fields (#2673)

Avoid repeatedly initializing the shared memory data when creating the child
thread in lib-pthread or lib-wasi-threads.

Add shared memory lock when accessing some fields of the memory instance
if the memory instance is shared.

Init shared memory's memory_data_size/memory_data_end fields according to
the current page count but not max page count.

Add wasm_runtime_set_mem_bound_check_bytes, and refine the error message
when shared memory flag is found but the feature isn't enabled.
This commit is contained in:
Wenyong Huang
2023-10-30 11:07:01 +08:00
committed by GitHub
parent 51a6b069d2
commit 4b1a6e5017
8 changed files with 195 additions and 110 deletions

View File

@ -298,10 +298,15 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm,
goto fail;
}
SHARED_MEMORY_LOCK(memory_inst);
if (app_offset + size <= memory_inst->memory_data_size) {
SHARED_MEMORY_UNLOCK(memory_inst);
return true;
}
SHARED_MEMORY_UNLOCK(memory_inst);
fail:
wasm_set_exception(module_inst, "out of bounds memory access");
return false;
@ -364,11 +369,16 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
goto fail;
}
SHARED_MEMORY_LOCK(memory_inst);
if (memory_inst->memory_data <= addr
&& addr + size <= memory_inst->memory_data_end) {
SHARED_MEMORY_UNLOCK(memory_inst);
return true;
}
SHARED_MEMORY_UNLOCK(memory_inst);
fail:
wasm_set_exception(module_inst, "out of bounds memory access");
return false;
@ -393,20 +403,24 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm,
return NULL;
}
SHARED_MEMORY_LOCK(memory_inst);
addr = memory_inst->memory_data + app_offset;
if (bounds_checks) {
if (memory_inst->memory_data <= addr
&& addr < memory_inst->memory_data_end) {
SHARED_MEMORY_UNLOCK(memory_inst);
return addr;
}
}
/* If bounds checks is disabled, return the address directly */
else if (app_offset != 0) {
SHARED_MEMORY_UNLOCK(memory_inst);
return addr;
}
SHARED_MEMORY_UNLOCK(memory_inst);
return NULL;
}
@ -418,6 +432,7 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm,
WASMMemoryInstance *memory_inst;
uint8 *addr = (uint8 *)native_ptr;
bool bounds_checks;
uint32 ret;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
@ -429,16 +444,24 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm,
return 0;
}
SHARED_MEMORY_LOCK(memory_inst);
if (bounds_checks) {
if (memory_inst->memory_data <= addr
&& addr < memory_inst->memory_data_end)
return (uint32)(addr - memory_inst->memory_data);
&& addr < memory_inst->memory_data_end) {
ret = (uint32)(addr - memory_inst->memory_data);
SHARED_MEMORY_UNLOCK(memory_inst);
return ret;
}
}
/* If bounds checks is disabled, return the offset directly */
else if (addr != NULL) {
return (uint32)(addr - memory_inst->memory_data);
ret = (uint32)(addr - memory_inst->memory_data);
SHARED_MEMORY_UNLOCK(memory_inst);
return ret;
}
SHARED_MEMORY_UNLOCK(memory_inst);
return 0;
}
@ -459,6 +482,8 @@ wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst_comm,
return false;
}
SHARED_MEMORY_LOCK(memory_inst);
memory_data_size = memory_inst->memory_data_size;
if (app_offset < memory_data_size) {
@ -466,9 +491,11 @@ wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst_comm,
*p_app_start_offset = 0;
if (p_app_end_offset)
*p_app_end_offset = memory_data_size;
SHARED_MEMORY_UNLOCK(memory_inst);
return true;
}
SHARED_MEMORY_UNLOCK(memory_inst);
return false;
}
@ -490,15 +517,19 @@ wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst_comm,
return false;
}
SHARED_MEMORY_LOCK(memory_inst);
if (memory_inst->memory_data <= addr
&& addr < memory_inst->memory_data_end) {
if (p_native_start_addr)
*p_native_start_addr = memory_inst->memory_data;
if (p_native_end_addr)
*p_native_end_addr = memory_inst->memory_data_end;
SHARED_MEMORY_UNLOCK(memory_inst);
return true;
}
SHARED_MEMORY_UNLOCK(memory_inst);
return false;
}
@ -512,9 +543,12 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
bool bounds_checks;
if (!memory_inst) {
goto fail;
wasm_set_exception(module_inst, "out of bounds memory access");
return false;
}
SHARED_MEMORY_LOCK(memory_inst);
native_addr = memory_inst->memory_data + app_buf_addr;
bounds_checks = is_bounds_checks_enabled((wasm_module_inst_t)module_inst);
@ -551,12 +585,18 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
}
#endif
SHARED_MEMORY_UNLOCK(memory_inst);
success:
*p_native_addr = (void *)native_addr;
return true;
#ifndef OS_ENABLE_HW_BOUND_CHECK
fail:
SHARED_MEMORY_UNLOCK(memory_inst);
wasm_set_exception(module_inst, "out of bounds memory access");
return false;
#endif
}
WASMMemoryInstance *
@ -568,6 +608,27 @@ wasm_get_default_memory(WASMModuleInstance *module_inst)
return NULL;
}
void
wasm_runtime_set_mem_bound_check_bytes(WASMMemoryInstance *memory,
uint64 memory_data_size)
{
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0
#if UINTPTR_MAX == UINT64_MAX
memory->mem_bound_check_1byte.u64 = memory_data_size - 1;
memory->mem_bound_check_2bytes.u64 = memory_data_size - 2;
memory->mem_bound_check_4bytes.u64 = memory_data_size - 4;
memory->mem_bound_check_8bytes.u64 = memory_data_size - 8;
memory->mem_bound_check_16bytes.u64 = memory_data_size - 16;
#else
memory->mem_bound_check_1byte.u32[0] = (uint32)memory_data_size - 1;
memory->mem_bound_check_2bytes.u32[0] = (uint32)memory_data_size - 2;
memory->mem_bound_check_4bytes.u32[0] = (uint32)memory_data_size - 4;
memory->mem_bound_check_8bytes.u32[0] = (uint32)memory_data_size - 8;
memory->mem_bound_check_16bytes.u32[0] = (uint32)memory_data_size - 16;
#endif
#endif
}
#ifndef OS_ENABLE_HW_BOUND_CHECK
bool
wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
@ -625,9 +686,10 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
memory->num_bytes_per_page = num_bytes_per_page;
memory->cur_page_count = total_page_count;
memory->max_page_count = max_page_count;
/* No need to update memory->memory_data_size as it is
initialized with the maximum memory data size for
shared memory */
memory->memory_data_size = (uint32)total_size_new;
memory->memory_data_end = memory->memory_data + (uint32)total_size_new;
wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new);
return true;
}
#endif
@ -679,21 +741,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
memory->memory_data = memory_data_new;
memory->memory_data_end = memory_data_new + (uint32)total_size_new;
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0
#if UINTPTR_MAX == UINT64_MAX
memory->mem_bound_check_1byte.u64 = total_size_new - 1;
memory->mem_bound_check_2bytes.u64 = total_size_new - 2;
memory->mem_bound_check_4bytes.u64 = total_size_new - 4;
memory->mem_bound_check_8bytes.u64 = total_size_new - 8;
memory->mem_bound_check_16bytes.u64 = total_size_new - 16;
#else
memory->mem_bound_check_1byte.u32[0] = (uint32)total_size_new - 1;
memory->mem_bound_check_2bytes.u32[0] = (uint32)total_size_new - 2;
memory->mem_bound_check_4bytes.u32[0] = (uint32)total_size_new - 4;
memory->mem_bound_check_8bytes.u32[0] = (uint32)total_size_new - 8;
memory->mem_bound_check_16bytes.u32[0] = (uint32)total_size_new - 16;
#endif
#endif
wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new);
#if defined(os_writegsbase)
/* write base addr of linear memory to GS segment register */
@ -799,13 +847,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
memory->memory_data_size = (uint32)total_size_new;
memory->memory_data_end = memory->memory_data + (uint32)total_size_new;
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0
memory->mem_bound_check_1byte.u64 = total_size_new - 1;
memory->mem_bound_check_2bytes.u64 = total_size_new - 2;
memory->mem_bound_check_4bytes.u64 = total_size_new - 4;
memory->mem_bound_check_8bytes.u64 = total_size_new - 8;
memory->mem_bound_check_16bytes.u64 = total_size_new - 16;
#endif
wasm_runtime_set_mem_bound_check_bytes(memory, total_size_new);
return_func:
if (!ret && enlarge_memory_error_cb) {

View File

@ -24,6 +24,10 @@ wasm_runtime_memory_destroy();
unsigned
wasm_runtime_memory_pool_size();
void
wasm_runtime_set_mem_bound_check_bytes(WASMMemoryInstance *memory,
uint64 memory_data_size);
void
wasm_runtime_set_enlarge_mem_error_callback(
const enlarge_memory_error_callback_t callback, void *user_data);

View File

@ -3038,7 +3038,8 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
}
}
strncpy(mapping_copy, map_dir_list[i], strlen(map_dir_list[i]) + 1);
bh_memcpy_s(mapping_copy, max_len, map_dir_list[i],
(uint32)(strlen(map_dir_list[i]) + 1));
map_mapped = strtok(mapping_copy, "::");
map_host = strtok(NULL, "::");

View File

@ -298,6 +298,14 @@ LOAD_I16(void *addr)
#endif /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */
#if WASM_ENABLE_SHARED_MEMORY != 0
#define SHARED_MEMORY_LOCK(memory) shared_memory_lock(memory)
#define SHARED_MEMORY_UNLOCK(memory) shared_memory_unlock(memory)
#else
#define SHARED_MEMORY_LOCK(memory) (void)0
#define SHARED_MEMORY_UNLOCK(memory) (void)0
#endif
typedef struct WASMModuleCommon {
/* Module type, for module loaded from WASM bytecode binary,
this field is Wasm_Module_Bytecode, and this structure should

View File

@ -301,12 +301,15 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
return -1;
}
shared_memory_lock(module_inst->memories[0]);
if ((uint8 *)address < module_inst->memories[0]->memory_data
|| (uint8 *)address + (wait64 ? 8 : 4)
> module_inst->memories[0]->memory_data_end) {
shared_memory_unlock(module_inst->memories[0]);
wasm_runtime_set_exception(module, "out of bounds memory access");
return -1;
}
shared_memory_unlock(module_inst->memories[0]);
#if WASM_ENABLE_THREAD_MGR != 0
exec_env =
@ -423,9 +426,11 @@ wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module, void *address,
bh_assert(module->module_type == Wasm_Module_Bytecode
|| module->module_type == Wasm_Module_AoT);
shared_memory_lock(module_inst->memories[0]);
out_of_bounds =
((uint8 *)address < module_inst->memories[0]->memory_data
|| (uint8 *)address + 4 > module_inst->memories[0]->memory_data_end);
shared_memory_unlock(module_inst->memories[0]);
if (out_of_bounds) {
wasm_runtime_set_exception(module, "out of bounds memory access");