Home | History | Annotate | Download | only in nonsfi
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <errno.h>
      6 #include <pthread.h>
      7 #include <signal.h>
      8 
      9 #include "components/nacl/loader/nonsfi/irt_interfaces.h"
     10 #include "native_client/src/include/nacl_macros.h"
     11 #include "native_client/src/shared/platform/nacl_log.h"
     12 #include "native_client/src/trusted/service_runtime/nacl_exception.h"
     13 #include "native_client/src/trusted/service_runtime/nacl_signal.h"
     14 
     15 namespace nacl {
     16 namespace nonsfi {
     17 namespace {
     18 
     19 // This is NonSFI version of exception handling codebase, NaCl side of
     20 // things resides in:
     21 // native_client/src/trusted/service_runtime/linux/nacl_signal.c
     22 // native_client/src/trusted/service_runtime/sys_exception.c
     23 
     24 // Crash signals to handle.  The differences from SFI NaCl are that
     25 // NonSFI NaCl does not use NACL_THREAD_SUSPEND_SIGNAL (==SIGUSR1),
     26 // and SIGSYS is reserved for seccomp-bpf.
     27 const int kSignals[] = {
     28   SIGSTKFLT,
     29   SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGBUS, SIGFPE, SIGSEGV,
     30   // Handle SIGABRT in case someone sends it asynchronously using kill().
     31   SIGABRT
     32 };
     33 
     34 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
     35 NaClExceptionHandler signal_handler_function_pointer = NULL;
     36 
     37 // Signal handler, responsible for calling the registered handler.
     38 void SignalCatch(int sig, siginfo_t* info, void* uc) {
     39   if (signal_handler_function_pointer) {
     40     NaClSignalContext signal_context;
     41     NaClSignalContextFromHandler(&signal_context, uc);
     42     NaClExceptionFrame exception_frame;
     43     NaClSignalSetUpExceptionFrame(&exception_frame,
     44                                   &signal_context,
     45                                   0 /* context_user_addr,
     46                                        not useful for NonSFI NaCl. */);
     47     signal_handler_function_pointer(&exception_frame.context);
     48   }
     49   _exit(-1);
     50 }
     51 
     52 int IrtExceptionHandler(NaClExceptionHandler handler,
     53                                NaClExceptionHandler* old_handler) {
     54   pthread_mutex_lock(&mutex);
     55   if (old_handler)
     56     *old_handler = signal_handler_function_pointer;
     57   signal_handler_function_pointer = handler;
     58   pthread_mutex_unlock(&mutex);
     59   return 0;
     60 }
     61 
     62 int IrtExceptionStack(void* stack, size_t size) {
     63   // TODO(uekawa): Implement this function so that the exception stack
     64   // actually gets used for running an exception handler.  Currently
     65   // we don't switch stack, which means we can't handle stack overflow
     66   // exceptions.
     67   return 0;
     68 }
     69 
     70 int IrtExceptionClearFlag(void) {
     71   // TODO(uekawa): Implement clear_flag() to behave like SFI NaCl's
     72   // implementation, so that a thread can handle a second exception
     73   // after handling a first exception
     74   return ENOSYS;
     75 }
     76 
     77 }  // namespace
     78 
     79 const struct nacl_irt_exception_handling kIrtExceptionHandling = {
     80   IrtExceptionHandler,
     81   IrtExceptionStack,
     82   IrtExceptionClearFlag,
     83 };
     84 
     85 void InitializeSignalHandler() {
     86   struct sigaction sa;
     87   unsigned int a;
     88 
     89   memset(&sa, 0, sizeof(sa));
     90   sigemptyset(&sa.sa_mask);
     91   sa.sa_sigaction = SignalCatch;
     92   sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
     93 
     94   // Mask all signals we catch to prevent re-entry.
     95   for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) {
     96     sigaddset(&sa.sa_mask, kSignals[a]);
     97   }
     98 
     99   // Install all handlers.
    100   for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) {
    101     if (sigaction(kSignals[a], &sa, NULL) != 0)
    102       NaClLog(LOG_FATAL, "sigaction to register signals failed.\n");
    103   }
    104 }
    105 
    106 }  // namespace nonsfi
    107 }  // namespace nacl
    108