diff options
author | Gus Caplan <me@gus.host> | 2019-04-15 16:09:51 -0500 |
---|---|---|
committer | Sam Roberts <vieuxtech@gmail.com> | 2019-05-16 10:52:53 -0700 |
commit | f2061930c83cb579410a7f26bed726d6568575e3 (patch) | |
tree | ddcfcc116344fd03d5d04721df49eacb0059dd13 /src | |
parent | cca375f4af235ed7e7f763b2e35532ae843a5854 (diff) | |
download | android-node-v8-f2061930c83cb579410a7f26bed726d6568575e3.tar.gz android-node-v8-f2061930c83cb579410a7f26bed726d6568575e3.tar.bz2 android-node-v8-f2061930c83cb579410a7f26bed726d6568575e3.zip |
src: enable V8's WASM trap handlers
This uses SIGSEGV handlers to catch WASM out of bound (OOB) memory
accesses instead of inserting OOB checks inline, resulting in a 25%-30%
speed increase.
Note that installing a custom SIGSEGV handler will break this, resulting
in potentially scary behaviour.
Refs: https://github.com/nodejs/node/issues/14927
PR-URL: https://github.com/nodejs/node/pull/27246
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Diffstat (limited to 'src')
-rw-r--r-- | src/inspector_agent.cc | 2 | ||||
-rw-r--r-- | src/node.cc | 58 | ||||
-rw-r--r-- | src/node.h | 15 | ||||
-rw-r--r-- | src/node_internals.h | 5 | ||||
-rw-r--r-- | src/node_watchdog.cc | 5 | ||||
-rw-r--r-- | src/node_watchdog.h | 2 |
6 files changed, 76 insertions, 11 deletions
diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index d8b5d01a28..d551c3a7d7 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -88,7 +88,7 @@ void StartIoInterrupt(Isolate* isolate, void* agent) { #ifdef __POSIX__ -static void StartIoThreadWakeup(int signo) { +static void StartIoThreadWakeup(int signo, siginfo_t* info, void* ucontext) { uv_sem_post(&start_io_thread_semaphore); } diff --git a/src/node.cc b/src/node.cc index 953465e04a..7dccd7ce57 100644 --- a/src/node.cc +++ b/src/node.cc @@ -70,6 +70,17 @@ #include "node_report.h" #endif +#if defined(__APPLE__) || defined(__linux__) +#define NODE_USE_V8_WASM_TRAP_HANDLER 1 +#else +#define NODE_USE_V8_WASM_TRAP_HANDLER 0 +#endif + +#if NODE_USE_V8_WASM_TRAP_HANDLER +#include <atomic> +#include "v8-wasm-trap-handler-posix.h" +#endif // NODE_USE_V8_WASM_TRAP_HANDLER + // ========== global C headers ========== #include <fcntl.h> // _O_RDWR @@ -177,7 +188,8 @@ void WaitForInspectorDisconnect(Environment* env) { #endif } -void SignalExit(int signo) { +#ifdef __POSIX__ +void SignalExit(int signo, siginfo_t* info, void* ucontext) { uv_tty_reset_mode(); #ifdef __FreeBSD__ // FreeBSD has a nasty bug, see RegisterSignalHandler for details @@ -188,6 +200,7 @@ void SignalExit(int signo) { #endif raise(signo); } +#endif // __POSIX__ MaybeLocal<Value> ExecuteBootstrapper(Environment* env, const char* id, @@ -434,14 +447,39 @@ void LoadEnvironment(Environment* env) { USE(StartMainThreadExecution(env)); } +#if NODE_USE_V8_WASM_TRAP_HANDLER +static std::atomic<void (*)(int signo, siginfo_t* info, void* ucontext)> + previous_sigsegv_action; + +void TrapWebAssemblyOrContinue(int signo, siginfo_t* info, void* ucontext) { + if (!v8::TryHandleWebAssemblyTrapPosix(signo, info, ucontext)) { + auto prev = previous_sigsegv_action.load(); + if (prev != nullptr) { + prev(signo, info, ucontext); + } else { + uv_tty_reset_mode(); + raise(signo); + } + } +} +#endif // NODE_USE_V8_WASM_TRAP_HANDLER #ifdef __POSIX__ void RegisterSignalHandler(int signal, - void (*handler)(int signal), + void (*handler)(int signal, + siginfo_t* info, + void* ucontext), bool reset_handler) { +#if NODE_USE_V8_WASM_TRAP_HANDLER + if (signal == SIGSEGV) { + CHECK(previous_sigsegv_action.is_lock_free()); + previous_sigsegv_action.store(handler); + return; + } +#endif // NODE_USE_V8_WASM_TRAP_HANDLER struct sigaction sa; memset(&sa, 0, sizeof(sa)); - sa.sa_handler = handler; + sa.sa_sigaction = handler; #ifndef __FreeBSD__ // FreeBSD has a nasty bug with SA_RESETHAND reseting the SA_SIGINFO, that is // in turn set for a libthr wrapper. This leads to a crash. @@ -499,6 +537,20 @@ inline void PlatformInit() { RegisterSignalHandler(SIGINT, SignalExit, true); RegisterSignalHandler(SIGTERM, SignalExit, true); +#if NODE_USE_V8_WASM_TRAP_HANDLER + // Tell V8 to disable emitting WebAssembly + // memory bounds checks. This means that we have + // to catch the SIGSEGV in TrapWebAssemblyOrContinue + // and pass the signal context to V8. + { + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = TrapWebAssemblyOrContinue; + CHECK_EQ(sigaction(SIGSEGV, &sa, nullptr), 0); + } + V8::EnableWebAssemblyTrapHandler(false); +#endif // NODE_USE_V8_WASM_TRAP_HANDLER + // Raise the open file descriptor limit. struct rlimit lim; if (getrlimit(RLIMIT_NOFILE, &lim) == 0 && lim.rlim_cur != lim.rlim_max) { diff --git a/src/node.h b/src/node.h index 5af0655a84..73a3998285 100644 --- a/src/node.h +++ b/src/node.h @@ -66,6 +66,10 @@ #include <memory> +#ifdef __POSIX__ +#include <signal.h> +#endif // __POSIX__ + #define NODE_MAKE_VERSION(major, minor, patch) \ ((major) * 0x1000 + (minor) * 0x100 + (patch)) @@ -816,6 +820,17 @@ class NODE_EXTERN AsyncResource { async_context async_context_; }; +#ifdef __POSIX__ +// Register a signal handler without interrupting +// any handlers that node itself needs. +NODE_EXTERN +void RegisterSignalHandler(int signal, + void (*handler)(int signal, + siginfo_t* info, + void* ucontext), + bool reset_handler = false); +#endif // __POSIX__ + } // namespace node #endif // SRC_NODE_H_ diff --git a/src/node_internals.h b/src/node_internals.h index 91cc0efd50..cb039f297b 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -91,11 +91,8 @@ void PrintCaughtException(v8::Isolate* isolate, const v8::TryCatch& try_catch); void WaitForInspectorDisconnect(Environment* env); -void SignalExit(int signo); #ifdef __POSIX__ -void RegisterSignalHandler(int signal, - void (*handler)(int signal), - bool reset_handler = false); +void SignalExit(int signal, siginfo_t* info, void* ucontext); #endif std::string GetHumanReadableProcessName(); diff --git a/src/node_watchdog.cc b/src/node_watchdog.cc index 7c62aafa82..28df2fb449 100644 --- a/src/node_watchdog.cc +++ b/src/node_watchdog.cc @@ -127,8 +127,9 @@ void* SigintWatchdogHelper::RunSigintWatchdog(void* arg) { return nullptr; } - -void SigintWatchdogHelper::HandleSignal(int signum) { +void SigintWatchdogHelper::HandleSignal(int signum, + siginfo_t* info, + void* ucontext) { uv_sem_post(&instance.sem_); } diff --git a/src/node_watchdog.h b/src/node_watchdog.h index 9c56b90e9e..36c2df1109 100644 --- a/src/node_watchdog.h +++ b/src/node_watchdog.h @@ -99,7 +99,7 @@ class SigintWatchdogHelper { bool stopping_; static void* RunSigintWatchdog(void* arg); - static void HandleSignal(int signum); + static void HandleSignal(int signum, siginfo_t* info, void* ucontext); #else bool watchdog_disabled_; static BOOL WINAPI WinCtrlCHandlerRoutine(DWORD dwCtrlType); |