diff options
Diffstat (limited to 'components/nacl/loader/nonsfi/irt_exception_handling.cc')
-rw-r--r-- | components/nacl/loader/nonsfi/irt_exception_handling.cc | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/components/nacl/loader/nonsfi/irt_exception_handling.cc b/components/nacl/loader/nonsfi/irt_exception_handling.cc new file mode 100644 index 0000000..c6bd26f --- /dev/null +++ b/components/nacl/loader/nonsfi/irt_exception_handling.cc @@ -0,0 +1,106 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <errno.h> +#include <pthread.h> +#include <signal.h> + +#include "components/nacl/loader/nonsfi/irt_interfaces.h" +#include "native_client/src/include/nacl_macros.h" +#include "native_client/src/trusted/service_runtime/nacl_exception.h" +#include "native_client/src/trusted/service_runtime/nacl_signal.h" + +namespace nacl { +namespace nonsfi { +namespace { + +// This is NonSFI version of exception handling codebase, NaCl side of +// things resides in: +// native_client/src/trusted/service_runtime/linux/nacl_signal.c +// native_client/src/trusted/service_runtime/sys_exception.c + +// Crash signals to handle. The differences from SFI NaCl are that +// NonSFI NaCl does not use NACL_THREAD_SUSPEND_SIGNAL (==SIGUSR1), +// and SIGSYS is reserved for seccomp-bpf. +const int kSignals[] = { + SIGSTKFLT, + SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGBUS, SIGFPE, SIGSEGV, + // Handle SIGABRT in case someone sends it asynchronously using kill(). + SIGABRT +}; + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +NaClExceptionHandler signal_handler_function_pointer = NULL; + +// Signal handler, responsible for calling the registered handler. +void SignalCatch(int sig, siginfo_t* info, void* uc) { + if (signal_handler_function_pointer) { + NaClSignalContext signal_context; + NaClSignalContextFromHandler(&signal_context, uc); + NaClExceptionFrame exception_frame; + NaClSignalSetUpExceptionFrame(&exception_frame, + &signal_context, + 0 /* context_user_addr, + not useful for NonSFI NaCl. */); + signal_handler_function_pointer(&exception_frame.context); + } + _exit(-1); +} + +int IrtExceptionHandler(NaClExceptionHandler handler, + NaClExceptionHandler* old_handler) { + pthread_mutex_lock(&mutex); + if (old_handler) + *old_handler = signal_handler_function_pointer; + signal_handler_function_pointer = handler; + pthread_mutex_unlock(&mutex); + return 0; +} + +int IrtExceptionStack(void* stack, size_t size) { + // TODO(uekawa): Implement this function so that the exception stack + // actually gets used for running an exception handler. Currently + // we don't switch stack, which means we can't handle stack overflow + // exceptions. + return 0; +} + +int IrtExceptionClearFlag(void) { + // TODO(uekawa): Implement clear_flag() to behave like SFI NaCl's + // implementation, so that a thread can handle a second exception + // after handling a first exception + return ENOSYS; +} + +} // namespace + +const struct nacl_irt_exception_handling kIrtExceptionHandling = { + IrtExceptionHandler, + IrtExceptionStack, + IrtExceptionClearFlag, +}; + +void InitializeSignalHandler() { + struct sigaction sa; + unsigned int a; + + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = SignalCatch; + sa.sa_flags = SA_ONSTACK | SA_SIGINFO; + + // Mask all signals we catch to prevent re-entry. + for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) { + sigaddset(&sa.sa_mask, kSignals[a]); + } + + // Install all handlers. + for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) { + if (sigaction(kSignals[a], &sa, NULL) != 0) + NaClLog(LOG_FATAL, "sigaction to register signals failed.\n"); + } +} + +} // namespace nonsfi +} // namespace nacl |