Bug 1737717 - Update wasm2c to report more crash info and support crash redirection r=glandium

Differential Revision: https://phabricator.services.mozilla.com/D129460
This commit is contained in:
shravanrn@gmail.com 2021-10-26 23:57:35 +00:00
parent 2a11cb1f78
commit 82440ca93b
9 changed files with 139 additions and 41 deletions

View File

@ -9,8 +9,8 @@ origin:
description: wasm2c fork used for rlbox sandboxing
url: https://github.com/PLSysSec/wasm2c_sandbox_compiler
release: commit 4249593a07e03f3d781862abb5a95c27aebf045d (2021-10-15T21:19:37Z).
revision: 4249593a07e03f3d781862abb5a95c27aebf045d
release: commit 247bd88bd77f07e3447ee168ed26d815de47b077 (2021-10-26T04:00:27Z).
revision: 247bd88bd77f07e3447ee168ed26d815de47b077
license: Apache-2.0
license-file: LICENSE

View File

@ -51,7 +51,7 @@ const char SECTION_NAME(declarations)[] =
" ((t)table.data[x].func)(__VA_ARGS__); \\\n"
" EXTERNAL_CALLBACK_EPILOGUE_EXEC(table, x); \\\n"
" } else { \\\n"
" (void) TRAP(CALL_INDIRECT); \\\n"
" wasm_rt_callback_error_trap(&table, x, func_types[ft]); \\\n"
" }\n"
"\n"
"#define CALL_INDIRECT_RES(res, table, t, ft, x, func_types, ...) \\\n"
@ -60,7 +60,7 @@ const char SECTION_NAME(declarations)[] =
" res = ((t)table.data[x].func)(__VA_ARGS__); \\\n"
" EXTERNAL_CALLBACK_EPILOGUE_EXEC(table, x); \\\n"
" } else { \\\n"
" (void) TRAP(CALL_INDIRECT); \\\n"
" wasm_rt_callback_error_trap(&table, x, func_types[ft]); \\\n"
" }\n"
"\n"
"#if defined(WASM_CHECK_SHADOW_MEMORY)\n"
@ -370,7 +370,7 @@ const char SECTION_NAME(sandboxapis)[] =
" return i;\n"
" }\n"
" }\n"
" (void) TRAP(CALL_INDIRECT);\n"
" (void) TRAP(CALL_INDIRECT_TABLE_EXPANSION);\n"
"}\n"
"\n"
"static void remove_wasm2c_callback(void* sbx_ptr, u32 callback_idx) {\n"

View File

@ -48,7 +48,7 @@
((t)table.data[x].func)(__VA_ARGS__); \
EXTERNAL_CALLBACK_EPILOGUE_EXEC(table, x); \
} else { \
(void) TRAP(CALL_INDIRECT); \
wasm_rt_callback_error_trap(&table, x, func_types[ft]); \
}
#define CALL_INDIRECT_RES(res, table, t, ft, x, func_types, ...) \
@ -57,7 +57,7 @@
res = ((t)table.data[x].func)(__VA_ARGS__); \
EXTERNAL_CALLBACK_EPILOGUE_EXEC(table, x); \
} else { \
(void) TRAP(CALL_INDIRECT); \
wasm_rt_callback_error_trap(&table, x, func_types[ft]); \
}
#if defined(WASM_CHECK_SHADOW_MEMORY)
@ -365,7 +365,7 @@ static u32 add_wasm2c_callback(void* sbx_ptr, u32 func_type_idx, void* func_ptr,
return i;
}
}
(void) TRAP(CALL_INDIRECT);
(void) TRAP(CALL_INDIRECT_TABLE_EXPANSION);
}
static void remove_wasm2c_callback(void* sbx_ptr, u32 callback_idx) {

View File

@ -220,7 +220,7 @@ typedef enum {
WASM_RT_TRAP_DIV_BY_ZERO,
WASM_RT_TRAP_INVALID_CONVERSION,
WASM_RT_TRAP_UNREACHABLE,
WASM_RT_TRAP_CALL_INDIRECT,
WASM_RT_TRAP_CALL_INDIRECT_TABLE_EXPANSION,
WASM_RT_TRAP_EXHAUSTION,
} wasm_rt_trap_t;
```

View File

@ -26,11 +26,93 @@
#include <stdlib.h>
#include <string.h>
#ifdef WASM_RT_CUSTOM_TRAP_HANDLER
// forward declare the signature of any custom trap handler
void WASM_RT_CUSTOM_TRAP_HANDLER(const char*);
#endif
void wasm_rt_trap(wasm_rt_trap_t code) {
assert(code != WASM_RT_TRAP_NONE);
const char* error_message = "wasm2c: unknown trap";
switch(code)
{
case WASM_RT_TRAP_NONE: {
// this should never happen
error_message = "wasm2c: WASM_RT_TRAP_NONE";
break;
}
case WASM_RT_TRAP_OOB: {
error_message = "wasm2c: WASM_RT_TRAP_OOB";
break;
}
case WASM_RT_TRAP_INT_OVERFLOW: {
error_message = "wasm2c: WASM_RT_TRAP_INT_OVERFLOW";
break;
}
case WASM_RT_TRAP_DIV_BY_ZERO: {
error_message = "wasm2c: WASM_RT_TRAP_DIV_BY_ZERO";
break;
}
case WASM_RT_TRAP_INVALID_CONVERSION: {
error_message = "wasm2c: WASM_RT_TRAP_INVALID_CONVERSION";
break;
}
case WASM_RT_TRAP_UNREACHABLE: {
error_message = "wasm2c: WASM_RT_TRAP_UNREACHABLE";
break;
}
case WASM_RT_TRAP_CALL_INDIRECT_TABLE_EXPANSION: {
error_message = "wasm2c: WASM_RT_TRAP_CALL_INDIRECT_TABLE_EXPANSION";
break;
}
case WASM_RT_TRAP_CALL_INDIRECT_OOB_INDEX: {
error_message = "wasm2c: WASM_RT_TRAP_CALL_INDIRECT_OOB_INDEX";
break;
}
case WASM_RT_TRAP_CALL_INDIRECT_NULL_PTR: {
error_message = "wasm2c: WASM_RT_TRAP_CALL_INDIRECT_NULL_PTR";
break;
}
case WASM_RT_TRAP_CALL_INDIRECT_TYPE_MISMATCH: {
error_message = "wasm2c: WASM_RT_TRAP_CALL_INDIRECT_TYPE_MISMATCH";
break;
}
case WASM_RT_TRAP_CALL_INDIRECT_UNKNOWN_ERR: {
error_message = "wasm2c: WASM_RT_TRAP_CALL_INDIRECT_UNKNOWN_ERR";
break;
}
case WASM_RT_TRAP_EXHAUSTION: {
error_message = "wasm2c: WASM_RT_TRAP_EXHAUSTION";
break;
}
case WASM_RT_TRAP_SHADOW_MEM: {
error_message = "wasm2c: WASM_RT_TRAP_SHADOW_MEM";
break;
}
case WASM_RT_TRAP_WASI: {
error_message = "wasm2c: WASM_RT_TRAP_WASI";
break;
}
};
#ifdef WASM_RT_CUSTOM_TRAP_HANDLER
WASM_RT_CUSTOM_TRAP_HANDLER(error_message);
#else
fprintf(stderr, "Error: %s\n", error_message);
abort();
#endif
}
void wasm_rt_callback_error_trap(wasm_rt_table_t* table, uint32_t func_index, uint32_t expected_func_type) {
if (func_index >= table->size) {
wasm_rt_trap(WASM_RT_TRAP_CALL_INDIRECT_OOB_INDEX);
} else if (!table->data[func_index].func) {
wasm_rt_trap(WASM_RT_TRAP_CALL_INDIRECT_NULL_PTR);
} else if (table->data[func_index].func_type != expected_func_type) {
wasm_rt_trap(WASM_RT_TRAP_CALL_INDIRECT_TYPE_MISMATCH);
}
wasm_rt_trap(WASM_RT_TRAP_CALL_INDIRECT_UNKNOWN_ERR);
}
static bool func_types_are_equal(wasm_func_type_t* a, wasm_func_type_t* b) {
if (a->param_count != b->param_count || a->result_count != b->result_count)
return 0;
@ -254,23 +336,23 @@ void wasm_rt_deallocate_table(wasm_rt_table_t* table) {
}
#define WASM_SATURATING_U32_ADD(ret_ptr, a, b) { \
if ((a) > (UINT32_MAX - (b))) { \
/* add will overflowed */ \
*ret_ptr = UINT32_MAX; \
} else { \
*ret_ptr = (a) + (b); \
} \
if ((a) > (UINT32_MAX - (b))) { \
/* add will overflowed */ \
*ret_ptr = UINT32_MAX; \
} else { \
*ret_ptr = (a) + (b); \
} \
}
#define WASM_CHECKED_U32_RET_SIZE_T_MULTIPLY(ret_ptr, a, b) { \
if ((a) > (SIZE_MAX / (b))) { \
/* multiple will overflowed */ \
wasm_rt_trap(WASM_RT_TRAP_CALL_INDIRECT); \
} else { \
/* convert to size by assigning */ \
*ret_ptr = a; \
*ret_ptr = *ret_ptr * b; \
} \
#define WASM_CHECKED_U32_RET_SIZE_T_MULTIPLY(ret_ptr, a, b) { \
if ((a) > (SIZE_MAX / (b))) { \
/* multiple will overflowed */ \
wasm_rt_trap(WASM_RT_TRAP_CALL_INDIRECT_TABLE_EXPANSION); \
} else { \
/* convert to size by assigning */ \
*ret_ptr = a; \
*ret_ptr = *ret_ptr * b; \
} \
}
void wasm_rt_expand_table(wasm_rt_table_t* table) {
@ -283,7 +365,7 @@ void wasm_rt_expand_table(wasm_rt_table_t* table) {
if (table->size == new_size) {
// table is already as large as we allowed, can't expand further
wasm_rt_trap(WASM_RT_TRAP_CALL_INDIRECT);
wasm_rt_trap(WASM_RT_TRAP_CALL_INDIRECT_TABLE_EXPANSION);
}
size_t allocation_size = 0;

View File

@ -4,6 +4,7 @@
#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || \
(defined(__APPLE__) && defined(__MACH__)))
#include "wasm-rt.h"
#include "wasm-rt-os.h"
#include <errno.h>
@ -188,13 +189,13 @@ void os_init() {
#if defined(__APPLE__) && defined(__MACH__)
// From here: https://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x/21352348#21352348
if (mach_timebase_info(&g_wasi_mac_clock_info.timebase) != 0) {
abort();
wasm_rt_trap(WASM_RT_TRAP_WASI);
}
// microseconds since 1 Jan 1970
struct timeval micro;
if (gettimeofday(&micro, NULL) != 0) {
abort();
wasm_rt_trap(WASM_RT_TRAP_WASI);
}
g_wasi_mac_clock_info.initclock = mach_absolute_time();
@ -214,7 +215,7 @@ void os_clock_init(void** clock_data_pointer) {
wasi_mac_clock_info_t* alloc = (wasi_mac_clock_info_t*) malloc(sizeof(wasi_mac_clock_info_t));
if (!alloc) {
abort();
wasm_rt_trap(WASM_RT_TRAP_WASI);
}
memcpy(alloc, &g_wasi_mac_clock_info, sizeof(wasi_mac_clock_info_t));
*clock_data_pointer = alloc;

View File

@ -3,6 +3,7 @@
// Check for windows (non cygwin) environment
#if defined(_WIN32)
#include "wasm-rt.h"
#include "wasm-rt-os.h"
#include <errno.h>
@ -227,7 +228,7 @@ static int g_os_data_initialized = 0;
void os_init() {
// From here: https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows/38212960#38212960
if (QueryPerformanceFrequency(&g_wasi_win_clock_info.counts_per_sec) == 0) {
abort();
wasm_rt_trap(WASM_RT_TRAP_WASI);
}
g_os_data_initialized = 1;
}
@ -239,7 +240,7 @@ void os_clock_init(void** clock_data_pointer) {
wasi_win_clock_info_t* alloc = (wasi_win_clock_info_t*) malloc(sizeof(wasi_win_clock_info_t));
if (!alloc) {
abort();
wasm_rt_trap(WASM_RT_TRAP_WASI);
}
memcpy(alloc, &g_wasi_win_clock_info, sizeof(wasi_win_clock_info_t));
*clock_data_pointer = alloc;

View File

@ -132,7 +132,7 @@ static void report_error(const char* func_name, const char* error_message, uint3
);
fflush(stdout);
#ifndef WASM_CHECK_SHADOW_MEMORY_NO_ABORT_ON_FAIL
abort();
wasm_rt_trap(WASM_RT_TRAP_SHADOW_MEM);
#endif
}

View File

@ -64,16 +64,24 @@ extern "C" {
#define WASM_RT_NO_RETURN __attribute__((noreturn))
#endif
/** Reason a trap occurred. Provide this to `wasm_rt_trap`. */
/** Reason a trap occurred. Provide this to `wasm_rt_trap`.
* If you update this enum also update the error message in wasm_rt_trap.
*/
typedef enum {
WASM_RT_TRAP_NONE, /** No error. */
WASM_RT_TRAP_OOB, /** Out-of-bounds access in linear memory. */
WASM_RT_TRAP_INT_OVERFLOW, /** Integer overflow on divide or truncation. */
WASM_RT_TRAP_DIV_BY_ZERO, /** Integer divide by zero. */
WASM_RT_TRAP_INVALID_CONVERSION, /** Conversion from NaN to integer. */
WASM_RT_TRAP_UNREACHABLE, /** Unreachable instruction executed. */
WASM_RT_TRAP_CALL_INDIRECT, /** Invalid call_indirect, for any reason. */
WASM_RT_TRAP_EXHAUSTION, /** Call stack exhausted. */
WASM_RT_TRAP_NONE, /** No error. */
WASM_RT_TRAP_OOB, /** Out-of-bounds access in linear memory. */
WASM_RT_TRAP_INT_OVERFLOW, /** Integer overflow on divide or truncation. */
WASM_RT_TRAP_DIV_BY_ZERO, /** Integer divide by zero. */
WASM_RT_TRAP_INVALID_CONVERSION, /** Conversion from NaN to integer. */
WASM_RT_TRAP_UNREACHABLE, /** Unreachable instruction executed. */
WASM_RT_TRAP_CALL_INDIRECT_TABLE_EXPANSION, /** Invalid call_indirect, as func table cannot grow/grow further. */
WASM_RT_TRAP_CALL_INDIRECT_OOB_INDEX, /** Invalid call_indirect, due to index larger than func table. */
WASM_RT_TRAP_CALL_INDIRECT_NULL_PTR, /** Invalid call_indirect, as function being invoked is null. */
WASM_RT_TRAP_CALL_INDIRECT_TYPE_MISMATCH, /** Invalid call_indirect, as function being invoked has an unexpected type. */
WASM_RT_TRAP_CALL_INDIRECT_UNKNOWN_ERR, /** Invalid call_indirect, for other reason. */
WASM_RT_TRAP_EXHAUSTION, /** Call stack exhausted. */
WASM_RT_TRAP_SHADOW_MEM, /** Trap due to shadow memory mismatch */
WASM_RT_TRAP_WASI, /** Trap due to WASI error */
} wasm_rt_trap_t;
/** Value types. Used to define function signatures. */
@ -197,6 +205,12 @@ typedef struct wasm2c_sandbox_funcs_t {
* This is typically called by the generated code, and not the embedder. */
WASM_RT_NO_RETURN extern void wasm_rt_trap(wasm_rt_trap_t);
/** An indirect callback function failed.
* Deduce the reason for the failure and then call trap.
*
* This is typically called by the generated code, and not the embedder. */
WASM_RT_NO_RETURN extern void wasm_rt_callback_error_trap(wasm_rt_table_t* table, uint32_t func_index, uint32_t expected_func_type);
/** Register a function type with the given signature. The returned function
* index is guaranteed to be the same for all calls with the same signature.
* The following varargs must all be of type `wasm_rt_type_t`, first the