Make memory access boundary check behavior configurable (#2289)
Allow to use `cmake -DWAMR_CONFIGURABLE_BOUNDS_CHECKS=1` to build iwasm, and then run `iwasm --disable-bounds-checks` to disable the memory access boundary checks. And add two APIs: `wasm_runtime_set_bounds_checks` and `wasm_runtime_is_bounds_checks_enabled`
This commit is contained in:
@ -456,4 +456,9 @@
|
||||
#define WASM_DISABLE_WRITE_GS_BASE 0
|
||||
#endif
|
||||
|
||||
/* Configurable bounds checks */
|
||||
#ifndef WASM_CONFIGURABLE_BOUNDS_CHECKS
|
||||
#define WASM_CONFIGURABLE_BOUNDS_CHECKS 0
|
||||
#endif
|
||||
|
||||
#endif /* end of _CONFIG_H_ */
|
||||
|
||||
@ -90,6 +90,10 @@ typedef struct AOTFunctionInstance {
|
||||
typedef struct AOTModuleInstanceExtra {
|
||||
DefPointer(const uint32 *, stack_sizes);
|
||||
CApiFuncImport *c_api_func_imports;
|
||||
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
|
||||
/* Disable bounds checks or not */
|
||||
bool disable_bounds_checks;
|
||||
#endif
|
||||
} AOTModuleInstanceExtra;
|
||||
|
||||
#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#include "wasm_runtime_common.h"
|
||||
#include "../interpreter/wasm_runtime.h"
|
||||
#include "../aot/aot_runtime.h"
|
||||
#include "bh_platform.h"
|
||||
#include "mem_alloc.h"
|
||||
|
||||
@ -87,6 +88,16 @@ wasm_memory_init_with_allocator(void *_malloc_func, void *_realloc_func,
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline bool
|
||||
is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst)
|
||||
{
|
||||
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
|
||||
return wasm_runtime_is_bounds_checks_enabled(module_inst);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
|
||||
const MemAllocOption *alloc_option)
|
||||
@ -269,6 +280,10 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm,
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
if (!is_bounds_checks_enabled(module_inst_comm)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (!memory_inst) {
|
||||
goto fail;
|
||||
@ -299,6 +314,10 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
if (!is_bounds_checks_enabled(module_inst_comm)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!wasm_runtime_get_app_addr_range(module_inst_comm, app_str_offset, NULL,
|
||||
&app_end_offset))
|
||||
goto fail;
|
||||
@ -327,6 +346,10 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
if (!is_bounds_checks_enabled(module_inst_comm)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (!memory_inst) {
|
||||
goto fail;
|
||||
@ -354,10 +377,13 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm,
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
WASMMemoryInstance *memory_inst;
|
||||
uint8 *addr;
|
||||
bool bounds_checks;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
bounds_checks = is_bounds_checks_enabled(module_inst_comm);
|
||||
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (!memory_inst) {
|
||||
return NULL;
|
||||
@ -365,8 +391,17 @@ wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm,
|
||||
|
||||
addr = memory_inst->memory_data + app_offset;
|
||||
|
||||
if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end)
|
||||
if (bounds_checks) {
|
||||
if (memory_inst->memory_data <= addr
|
||||
&& addr < memory_inst->memory_data_end) {
|
||||
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
/* If bounds checks is disabled, return the address directly */
|
||||
else if (app_offset != 0) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -378,17 +413,27 @@ wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm,
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
WASMMemoryInstance *memory_inst;
|
||||
uint8 *addr = (uint8 *)native_ptr;
|
||||
bool bounds_checks;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
|
||||
bounds_checks = is_bounds_checks_enabled(module_inst_comm);
|
||||
|
||||
memory_inst = wasm_get_default_memory(module_inst);
|
||||
if (!memory_inst) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end)
|
||||
if (bounds_checks) {
|
||||
if (memory_inst->memory_data <= addr
|
||||
&& addr < memory_inst->memory_data_end)
|
||||
return (uint32)(addr - memory_inst->memory_data);
|
||||
}
|
||||
/* If bounds checks is disabled, return the offset directly */
|
||||
else if (addr != NULL) {
|
||||
return (uint32)(addr - memory_inst->memory_data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -460,6 +505,7 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
|
||||
{
|
||||
WASMMemoryInstance *memory_inst = wasm_get_default_memory(module_inst);
|
||||
uint8 *native_addr;
|
||||
bool bounds_checks;
|
||||
|
||||
if (!memory_inst) {
|
||||
goto fail;
|
||||
@ -467,6 +513,15 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
|
||||
|
||||
native_addr = memory_inst->memory_data + app_buf_addr;
|
||||
|
||||
bounds_checks = is_bounds_checks_enabled((wasm_module_inst_t)module_inst);
|
||||
|
||||
if (!bounds_checks) {
|
||||
if (app_buf_addr == 0) {
|
||||
native_addr = NULL;
|
||||
}
|
||||
goto success;
|
||||
}
|
||||
|
||||
/* No need to check the app_offset and buf_size if memory access
|
||||
boundary check with hardware trap is enabled */
|
||||
#ifndef OS_ENABLE_HW_BOUND_CHECK
|
||||
@ -492,6 +547,7 @@ wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
|
||||
}
|
||||
#endif
|
||||
|
||||
success:
|
||||
*p_native_addr = (void *)native_addr;
|
||||
return true;
|
||||
fail:
|
||||
|
||||
@ -2482,6 +2482,54 @@ wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst_comm)
|
||||
return module_inst->custom_data;
|
||||
}
|
||||
|
||||
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
|
||||
void
|
||||
wasm_runtime_set_bounds_checks(WASMModuleInstanceCommon *module_inst,
|
||||
bool enable)
|
||||
{
|
||||
/* Alwary disable bounds checks if hw bounds checks enabled */
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
enable = false;
|
||||
#endif
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)->e)
|
||||
->disable_bounds_checks = enable ? false : true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
((AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e)
|
||||
->disable_bounds_checks = enable ? false : true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
wasm_runtime_is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst)
|
||||
{
|
||||
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (module_inst->module_type == Wasm_Module_Bytecode) {
|
||||
return !((WASMModuleInstanceExtra *)((WASMModuleInstance *)module_inst)
|
||||
->e)
|
||||
->disable_bounds_checks;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (module_inst->module_type == Wasm_Module_AoT) {
|
||||
return !((AOTModuleInstanceExtra *)((WASMModuleInstance *)module_inst)
|
||||
->e)
|
||||
->disable_bounds_checks;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32
|
||||
wasm_runtime_module_malloc_internal(WASMModuleInstanceCommon *module_inst,
|
||||
WASMExecEnv *exec_env, uint32 size,
|
||||
|
||||
@ -593,6 +593,17 @@ wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data);
|
||||
WASM_RUNTIME_API_EXTERN void *
|
||||
wasm_runtime_get_user_data(WASMExecEnv *exec_env);
|
||||
|
||||
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_bounds_checks(WASMModuleInstanceCommon *module_inst,
|
||||
bool enable);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_is_bounds_checks_enabled(WASMModuleInstanceCommon *module_inst);
|
||||
#endif
|
||||
|
||||
#ifdef OS_ENABLE_HW_BOUND_CHECK
|
||||
/* Access exception check guard page to trigger the signal handler */
|
||||
void
|
||||
|
||||
@ -914,6 +914,25 @@ wasm_runtime_set_custom_data(wasm_module_inst_t module_inst,
|
||||
WASM_RUNTIME_API_EXTERN void *
|
||||
wasm_runtime_get_custom_data(wasm_module_inst_t module_inst);
|
||||
|
||||
/**
|
||||
* Set the memory bounds checks flag of a WASM module instance.
|
||||
*
|
||||
* @param module_inst the WASM module instance
|
||||
* @param enable the flag to enable/disable the memory bounds checks
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_bounds_checks(wasm_module_inst_t module_inst,
|
||||
bool enable);
|
||||
/**
|
||||
* Check if the memory bounds checks flag is enabled for a WASM module instance.
|
||||
*
|
||||
* @param module_inst the WASM module instance
|
||||
*
|
||||
* @return true if the memory bounds checks flag is enabled, false otherwise
|
||||
*/
|
||||
WASM_RUNTIME_API_EXTERN bool
|
||||
wasm_runtime_is_bounds_checks_enabled(
|
||||
wasm_module_inst_t module_inst);
|
||||
/**
|
||||
* Allocate memory from the heap of WASM module instance
|
||||
*
|
||||
|
||||
@ -41,26 +41,28 @@ typedef float64 CellType_F64;
|
||||
|
||||
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|
||||
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
|
||||
#define CHECK_MEMORY_OVERFLOW(bytes) \
|
||||
do { \
|
||||
uint64 offset1 = (uint64)offset + (uint64)addr; \
|
||||
if (offset1 + bytes <= (uint64)get_linear_mem_size()) \
|
||||
/* If offset1 is in valid range, maddr must also \
|
||||
be in valid range, no need to check it again. */ \
|
||||
maddr = memory->memory_data + offset1; \
|
||||
else \
|
||||
goto out_of_bounds; \
|
||||
#define CHECK_MEMORY_OVERFLOW(bytes) \
|
||||
do { \
|
||||
uint64 offset1 = (uint64)offset + (uint64)addr; \
|
||||
if (disable_bounds_checks \
|
||||
|| offset1 + bytes <= (uint64)get_linear_mem_size()) \
|
||||
/* If offset1 is in valid range, maddr must also \
|
||||
be in valid range, no need to check it again. */ \
|
||||
maddr = memory->memory_data + offset1; \
|
||||
else \
|
||||
goto out_of_bounds; \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
|
||||
do { \
|
||||
uint64 offset1 = (uint32)(start); \
|
||||
if (offset1 + bytes <= (uint64)get_linear_mem_size()) \
|
||||
/* App heap space is not valid space for \
|
||||
bulk memory operation */ \
|
||||
maddr = memory->memory_data + offset1; \
|
||||
else \
|
||||
goto out_of_bounds; \
|
||||
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
|
||||
do { \
|
||||
uint64 offset1 = (uint32)(start); \
|
||||
if (disable_bounds_checks \
|
||||
|| offset1 + bytes <= (uint64)get_linear_mem_size()) \
|
||||
/* App heap space is not valid space for \
|
||||
bulk memory operation */ \
|
||||
maddr = memory->memory_data + offset1; \
|
||||
else \
|
||||
goto out_of_bounds; \
|
||||
} while (0)
|
||||
#else
|
||||
#define CHECK_MEMORY_OVERFLOW(bytes) \
|
||||
@ -1174,6 +1176,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint8 local_type, *global_addr;
|
||||
uint32 cache_index, type_index, param_cell_num, cell_num;
|
||||
uint8 value_type;
|
||||
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
|
||||
bool disable_bounds_checks = !wasm_runtime_is_bounds_checks_enabled(
|
||||
(WASMModuleInstanceCommon *)module);
|
||||
#else
|
||||
bool disable_bounds_checks = false;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_DEBUG_INTERP != 0
|
||||
uint8 *frame_ip_orig = NULL;
|
||||
|
||||
@ -35,7 +35,8 @@ typedef float64 CellType_F64;
|
||||
#define CHECK_MEMORY_OVERFLOW(bytes) \
|
||||
do { \
|
||||
uint64 offset1 = (uint64)offset + (uint64)addr; \
|
||||
if (offset1 + bytes <= (uint64)get_linear_mem_size()) \
|
||||
if (disable_bounds_checks \
|
||||
|| offset1 + bytes <= (uint64)get_linear_mem_size()) \
|
||||
/* If offset1 is in valid range, maddr must also \
|
||||
be in valid range, no need to check it again. */ \
|
||||
maddr = memory->memory_data + offset1; \
|
||||
@ -43,15 +44,15 @@ typedef float64 CellType_F64;
|
||||
goto out_of_bounds; \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
|
||||
do { \
|
||||
uint64 offset1 = (uint32)(start); \
|
||||
if (offset1 + bytes <= get_linear_mem_size()) \
|
||||
/* App heap space is not valid space for \
|
||||
bulk memory operation */ \
|
||||
maddr = memory->memory_data + offset1; \
|
||||
else \
|
||||
goto out_of_bounds; \
|
||||
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
|
||||
do { \
|
||||
uint64 offset1 = (uint32)(start); \
|
||||
if (disable_bounds_checks || offset1 + bytes <= get_linear_mem_size()) \
|
||||
/* App heap space is not valid space for \
|
||||
bulk memory operation */ \
|
||||
maddr = memory->memory_data + offset1; \
|
||||
else \
|
||||
goto out_of_bounds; \
|
||||
} while (0)
|
||||
#else
|
||||
#define CHECK_MEMORY_OVERFLOW(bytes) \
|
||||
@ -1199,6 +1200,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
|
||||
uint8 *maddr = NULL;
|
||||
uint32 local_idx, local_offset, global_idx;
|
||||
uint8 opcode, local_type, *global_addr;
|
||||
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
|
||||
bool disable_bounds_checks = !wasm_runtime_is_bounds_checks_enabled(
|
||||
(WASMModuleInstanceCommon *)module);
|
||||
#else
|
||||
bool disable_bounds_checks = false;
|
||||
#endif
|
||||
|
||||
#if WASM_ENABLE_LABELS_AS_VALUES != 0
|
||||
#define HANDLE_OPCODE(op) &&HANDLE_##op
|
||||
|
||||
@ -241,6 +241,10 @@ typedef struct WASMModuleInstanceExtra {
|
||||
&& WASM_ENABLE_LAZY_JIT != 0)
|
||||
WASMModuleInstance *next;
|
||||
#endif
|
||||
#if WASM_CONFIGUABLE_BOUNDS_CHECKS != 0
|
||||
/* Disable bounds checks or not */
|
||||
bool disable_bounds_checks;
|
||||
#endif
|
||||
} WASMModuleInstanceExtra;
|
||||
|
||||
struct AOTFuncPerfProfInfo;
|
||||
|
||||
Reference in New Issue
Block a user