diff options
author | Keith Winstein <keithw@cs.stanford.edu> | 2023-11-28 11:13:22 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-28 19:13:22 +0000 |
commit | 9944d92c821087de96262792ff2333f97be2d528 (patch) | |
tree | 2b5d170e95552dcfab3903a7128530fd47d5ab09 /wasm2c | |
parent | b85cbadb19be5f060cd1d23e53e2d19940c5b571 (diff) | |
download | wabt-9944d92c821087de96262792ff2333f97be2d528.tar.gz wabt-9944d92c821087de96262792ff2333f97be2d528.tar.bz2 wabt-9944d92c821087de96262792ff2333f97be2d528.zip |
wasm2c runtime: refactor handling of alternate stack (NFC) (#2338)
The runtime installs an alternate stack to handle SIGSEGV
from stack exhaustion. Make this variable thread-local
and refactor implementation that touches it.
Diffstat (limited to 'wasm2c')
-rw-r--r-- | wasm2c/wasm-rt-impl.c | 93 |
1 files changed, 81 insertions, 12 deletions
diff --git a/wasm2c/wasm-rt-impl.c b/wasm2c/wasm-rt-impl.c index 99bae707..8cbe0e4a 100644 --- a/wasm2c/wasm-rt-impl.c +++ b/wasm2c/wasm-rt-impl.c @@ -42,14 +42,14 @@ static bool g_signal_handler_installed = false; #ifdef _WIN32 static void* g_sig_handler_handle = 0; -#else -static char* g_alt_stack = 0; #endif #endif #if WASM_RT_USE_STACK_DEPTH_COUNT WASM_RT_THREAD_LOCAL uint32_t wasm_rt_call_stack_depth; WASM_RT_THREAD_LOCAL uint32_t wasm_rt_saved_call_stack_depth; +#elif WASM_RT_INSTALL_SIGNAL_HANDLER +static WASM_RT_THREAD_LOCAL void* g_alt_stack = NULL; #endif WASM_RT_THREAD_LOCAL wasm_rt_jmp_buf g_wasm_rt_jmp_buf; @@ -172,14 +172,36 @@ static void os_signal_handler(int sig, siginfo_t* si, void* unused) { } } -static void os_install_signal_handler(void) { - /* Use alt stack to handle SIGSEGV from stack overflow */ +#if !WASM_RT_USE_STACK_DEPTH_COUNT +/* These routines set up an altstack to handle SIGSEGV from stack overflow. */ +static bool os_has_altstack_installed() { + /* check for altstack already in place */ + stack_t ss; + if (sigaltstack(NULL, &ss) != 0) { + perror("sigaltstack failed"); + abort(); + } + + return !(ss.ss_flags & SS_DISABLE); +} + +static void os_allocate_and_install_altstack(void) { + /* verify altstack not already allocated */ + assert(!g_alt_stack && + "wasm-rt error: tried to re-allocate thread-local alternate stack\n"); + + /* We could check and warn if an altstack is already installed, but some + * sanitizers install their own altstack, so this warning would fire + * spuriously and break the test outputs. */ + + /* allocate altstack */ g_alt_stack = malloc(SIGSTKSZ); if (g_alt_stack == NULL) { perror("malloc failed"); abort(); } + /* install altstack */ stack_t ss; ss.ss_sp = g_alt_stack; ss.ss_flags = 0; @@ -188,10 +210,51 @@ static void os_install_signal_handler(void) { perror("sigaltstack failed"); abort(); } +} + +static void os_disable_and_deallocate_altstack(void) { + /* in debug build, verify altstack allocated */ +#ifndef NDEBUG + if (!g_alt_stack) { + fprintf(stderr, "wasm-rt error: alternate stack is NULL\n"); + abort(); + } +#endif + + /* verify altstack was still in place */ + stack_t ss; + if (sigaltstack(NULL, &ss) != 0) { + perror("sigaltstack failed"); + abort(); + } + + if ((!g_alt_stack) || (ss.ss_flags & SS_DISABLE) || + (ss.ss_sp != g_alt_stack) || (ss.ss_size != SIGSTKSZ)) { +#ifndef NDEBUG + fprintf(stderr, + "wasm-rt warning: alternate stack was modified unexpectedly\n"); +#endif + return; + } + + /* disable and free */ + ss.ss_flags = SS_DISABLE; + if (sigaltstack(&ss, NULL) != 0) { + perror("sigaltstack failed"); + abort(); + } + assert(!os_has_altstack_installed()); + free(g_alt_stack); +} +#endif +static void os_install_signal_handler(void) { struct sigaction sa; memset(&sa, '\0', sizeof(sa)); - sa.sa_flags = SA_SIGINFO | SA_ONSTACK; + sa.sa_flags = SA_SIGINFO; +#if !WASM_RT_USE_STACK_DEPTH_COUNT + sa.sa_flags |= SA_ONSTACK; +#endif sigemptyset(&sa.sa_mask); sa.sa_sigaction = os_signal_handler; @@ -211,13 +274,6 @@ static void os_cleanup_signal_handler(void) { perror("sigaction failed"); abort(); } - - if (sigaltstack(NULL, NULL) != 0) { - perror("sigaltstack failed"); - abort(); - } - - free(g_alt_stack); } #endif @@ -227,12 +283,21 @@ void wasm_rt_init(void) { #if WASM_RT_INSTALL_SIGNAL_HANDLER if (!g_signal_handler_installed) { g_signal_handler_installed = true; +#if !WASM_RT_USE_STACK_DEPTH_COUNT + os_allocate_and_install_altstack(); +#endif os_install_signal_handler(); } #endif + assert(wasm_rt_is_initialized()); } bool wasm_rt_is_initialized(void) { +#if !WASM_RT_USE_STACK_DEPTH_COUNT + if (!os_has_altstack_installed()) { + return false; + } +#endif #if WASM_RT_INSTALL_SIGNAL_HANDLER return g_signal_handler_installed; #else @@ -241,8 +306,12 @@ bool wasm_rt_is_initialized(void) { } void wasm_rt_free(void) { + assert(wasm_rt_is_initialized()); #if WASM_RT_INSTALL_SIGNAL_HANDLER os_cleanup_signal_handler(); +#if !WASM_RT_USE_STACK_DEPTH_COUNT + os_disable_and_deallocate_altstack(); +#endif g_signal_handler_installed = false; #endif } |