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 #if !defined(__mips__)
     29   // This signal does not exist on MIPS.
     30   SIGSTKFLT,
     31 #endif
     32   SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGBUS, SIGFPE, SIGSEGV,
     33   // Handle SIGABRT in case someone sends it asynchronously using kill().
     34   SIGABRT
     35 };
     36 
     37 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
     38 NaClExceptionHandler signal_handler_function_pointer = NULL;
     39 
     40 // Signal handler, responsible for calling the registered handler.
     41 void SignalCatch(int sig, siginfo_t* info, void* uc) {
     42   if (signal_handler_function_pointer) {
     43     NaClSignalContext signal_context;
     44     NaClSignalContextFromHandler(&signal_context, uc);
     45     NaClExceptionFrame exception_frame;
     46     NaClSignalSetUpExceptionFrame(&exception_frame,
     47                                   &signal_context,
     48                                   0 /* context_user_addr,
     49                                        not useful for NonSFI NaCl. */);
     50     signal_handler_function_pointer(&exception_frame.context);
     51   }
     52   _exit(-1);
     53 }
     54 
     55 int IrtExceptionHandler(NaClExceptionHandler handler,
     56                                NaClExceptionHandler* old_handler) {
     57   pthread_mutex_lock(&mutex);
     58   if (old_handler)
     59     *old_handler = signal_handler_function_pointer;
     60   signal_handler_function_pointer = handler;
     61   pthread_mutex_unlock(&mutex);
     62   return 0;
     63 }
     64 
     65 int IrtExceptionStack(void* stack, size_t size) {
     66   // TODO(uekawa): Implement this function so that the exception stack
     67   // actually gets used for running an exception handler.  Currently
     68   // we don't switch stack, which means we can't handle stack overflow
     69   // exceptions.
     70   return 0;
     71 }
     72 
     73 int IrtExceptionClearFlag(void) {
     74   // TODO(uekawa): Implement clear_flag() to behave like SFI NaCl's
     75   // implementation, so that a thread can handle a second exception
     76   // after handling a first exception
     77   return ENOSYS;
     78 }
     79 
     80 }  // namespace
     81 
     82 const struct nacl_irt_exception_handling kIrtExceptionHandling = {
     83   IrtExceptionHandler,
     84   IrtExceptionStack,
     85   IrtExceptionClearFlag,
     86 };
     87 
     88 void InitializeSignalHandler() {
     89   struct sigaction sa;
     90   unsigned int a;
     91 
     92   memset(&sa, 0, sizeof(sa));
     93   sigemptyset(&sa.sa_mask);
     94   sa.sa_sigaction = SignalCatch;
     95   sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
     96 
     97   // Mask all signals we catch to prevent re-entry.
     98   for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) {
     99     sigaddset(&sa.sa_mask, kSignals[a]);
    100   }
    101 
    102   // Install all handlers.
    103   for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) {
    104     if (sigaction(kSignals[a], &sa, NULL) != 0)
    105       NaClLog(LOG_FATAL, "sigaction to register signals failed.\n");
    106   }
    107 }
    108 
    109 }  // namespace nonsfi
    110 }  // namespace nacl
    111