| Index: components/nacl/loader/nonsfi/irt_exception_handling.cc
|
| 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 0000000000000000000000000000000000000000..c4606b5e6a6573219a1997ed205f8ce5b87a335e
|
| --- /dev/null
|
| +++ b/components/nacl/loader/nonsfi/irt_exception_handling.cc
|
| @@ -0,0 +1,118 @@
|
| +// 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 <signal.h>
|
| +
|
| +#include <map>
|
| +
|
| +#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 {
|
| +
|
| +/* NaCl side of things resides in:
|
| + * native_client/src/trusted/service_runtime/linux/nacl_signal.c
|
| + */
|
| +
|
| +// TODO(uekawa): The list of signals to be handled might need updating.
|
| +static const int kSignals[] = {
|
| + SIGSTKFLT,
|
| + // SIGSYS, /* sigsys is reserved for seccomp-bpf */
|
| + // NACL_THREAD_SUSPEND_SIGNAL, // what is this signal?
|
| + SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGBUS, SIGFPE, SIGSEGV,
|
| + /* Handle SIGABRT in case someone sends it asynchronously using kill(). */
|
| + SIGABRT
|
| +};
|
| +
|
| +NaClExceptionHandler signal_handler_function_pointer = NULL;
|
| +
|
| +// Signal handler, responsible for calling the registered handlers.
|
| +static void SignalCatch(int sig, siginfo_t *info, void *uc) {
|
| + if (signal_handler_function_pointer) {
|
| + NaClSignalContext signal_context;
|
| + NaClSignalContextFromHandler(&signal_context, uc);
|
| + // Is this safe to allocate this on stack ?
|
| + NaClExceptionFrame exception_frame;
|
| + NaClSignalSetUpExceptionFrame(&exception_frame,
|
| + &signal_context,
|
| + 0 /* context_user_addr, what is this? */);
|
| +
|
| + signal_handler_function_pointer(&exception_frame.context);
|
| + }
|
| + // TODO(uekawa): only exit on crash signals ?
|
| + _exit(-1);
|
| +}
|
| +
|
| +// Based off NaCl version
|
| +// native_client/src/trusted/service_runtime/sys_exception.c
|
| +static int IrtExceptionHandler(NaClExceptionHandler handler,
|
| + NaClExceptionHandler *old_handler) {
|
| + // TODO(uekawa): Do I need to mutex lock?
|
| + if (old_handler) {
|
| + *old_handler = signal_handler_function_pointer;
|
| + }
|
| + signal_handler_function_pointer = handler;
|
| + return 0;
|
| +}
|
| +
|
| +static int IrtExceptionStack(void *stack, size_t size) {
|
| + // TODO(uekawa): implement for unit tests? IrtThreadCreate allocates
|
| + // sigaltstack and there's very little point in re-allocating a new
|
| + // altstack. Note, this is required by
|
| + // tests/exception_test/exception_crash_test.c
|
| + return -EINVAL;
|
| +}
|
| +
|
| +static int IrtExceptionClearFlag(void) {
|
| + // TODO(uekawa): I think we shouldn't implement this for now.
|
| + return -EINVAL;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +const struct nacl_irt_exception_handling kIrtExceptionHandling = {
|
| + IrtExceptionHandler,
|
| + IrtExceptionStack,
|
| + IrtExceptionClearFlag,
|
| +};
|
| +
|
| +void InitializeSignalHandler(void) {
|
| + 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.
|
| + *
|
| + * In particular, NACL_THREAD_SUSPEND_SIGNAL must be masked while we
|
| + * are handling a fault from untrusted code, otherwise the
|
| + * suspension signal will interrupt the trusted fault handler. That
|
| + * would cause NaClAppThreadGetSuspendedRegisters() to report
|
| + * trusted-code register state rather than untrusted-code register
|
| + * state from the point where the fault occurred.
|
| + */
|
| + 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) {
|
| + // TODO: log something when things fail. This is bad.
|
| + perror("sigaction");
|
| + // LOG(FATAL) << "Failed to install signal handler";
|
| + }
|
| + }
|
| +}
|
| +
|
| +} // namespace nonsfi
|
| +} // namespace nacl
|
|
|