示例#1
0
static void FindAndRunHandler(int sig, siginfo_t *info, void *uc) {
  if (NaClSignalHandlerFind(sig, uc) == NACL_SIGNAL_SEARCH) {
    int a;

    /* If we need to keep searching, try the old signal handler. */
    for (a = 0; a < SIGNAL_COUNT; a++) {
      /* If we handle this signal */
      if (s_Signals[a] == sig) {
        /* If this is a real sigaction pointer... */
        if (s_OldActions[a].sa_flags & SA_SIGINFO) {
          /* then call the old handler. */
          s_OldActions[a].sa_sigaction(sig, info, uc);
          break;
        }
        /* otherwise check if it is a real signal pointer */
        if ((s_OldActions[a].sa_handler != SIG_DFL) &&
            (s_OldActions[a].sa_handler != SIG_IGN)) {
          /* and call the old signal. */
          s_OldActions[a].sa_handler(sig);
          break;
        }
        /*
         * We matched the signal, but didn't handle it, so we emulate
         * the default behavior which is to exit the app with the signal
         * number as the error code.
         */
        NaClSignalErrorMessage("Failed to handle signal.\n");
        NaClExit(-sig);
      }
    }
  }
}
示例#2
0
void NaClSignalHandlerInit() {
  int a;

  /* Build the free list */
  for (a = 0; a < MAX_NACL_HANDLERS; a++) {
    s_SignalNodes[a].next = s_FreeList;
    s_SignalNodes[a].id = a + 1;
    s_FreeList = &s_SignalNodes[a];
  }

  NaClSignalHandlerInitPlatform();
#ifdef NACL_STANDALONE
  /* In stand-alone mode (sel_ldr) we handle all signals. */
  NaClSignalHandlerAdd(NaClSignalHandleAll);
#else
  /*
   * When run in Chrome we handle only signals in untrusted code.
   * Signals in trusted code are allowed to pass back to Chrome so
   * that Breakpad can create a minidump when applicable.
   */
  NaClSignalHandlerAdd(NaClSignalHandleUntrusted);
#endif
  if (getenv("NACL_CRASH_TEST") != NULL) {
    NaClSignalErrorMessage("[CRASH_TEST] Causing crash in NaCl "
                           "trusted code...\n");
    /* Clang removes non-volatile NULL pointer references. */
    *(volatile int *) 0 = 0;
  }
}
示例#3
0
enum NaClSignalResult NaClSignalHandleUntrusted(int signal, void *ctx) {
  struct NaClSignalContext sigCtx;
  char tmp[128];
  /*
   * Return an 8 bit error code which is -signal to
   * simulate normal OS behavior
   */
  NaClSignalContextFromHandler(&sigCtx, ctx);
  if (NaClSignalContextIsUntrusted(&sigCtx)) {
    SNPRINTF(tmp, sizeof(tmp), "\n** Signal %d from untrusted code: Halting "
             "at %" NACL_PRIXNACL_REG "h\n", signal, sigCtx.prog_ctr);
    NaClSignalErrorMessage(tmp);
    NaClExit((-signal) & 0xFF);
  }
  else {
    SNPRINTF(tmp, sizeof(tmp), "\n** Signal %d from trusted code: Continuing "
             "from %" NACL_PRIXNACL_REG "h\n", signal, sigCtx.prog_ctr);
    NaClSignalErrorMessage(tmp);
  }
  return NACL_SIGNAL_SEARCH;
}
示例#4
0
static void HandleSuspendSignal(struct NaClSignalContext *regs) {
  uint32_t tls_idx = NaClTlsGetIdx();
  struct NaClAppThread *natp = nacl_thread[tls_idx];
  struct NaClSignalContext *suspended_registers =
      &natp->suspended_registers->context;

  /* Sanity check. */
  if (natp->suspend_state != (NACL_APP_THREAD_UNTRUSTED |
                              NACL_APP_THREAD_SUSPENDING)) {
    NaClSignalErrorMessage("HandleSuspendSignal: "
                           "Unexpected suspend_state\n");
    NaClAbort();
  }

  if (suspended_registers != NULL) {
    *suspended_registers = *regs;
    /*
     * Ensure that the change to natp->suspend_state does not become
     * visible before the change to natp->suspended_registers.
     */
    NaClWriteMemoryBarrier();
  }

  /*
   * Indicate that we have suspended by setting
   * NACL_APP_THREAD_SUSPENDED.  We should not need an atomic
   * operation for this since the calling thread will not be trying to
   * change suspend_state.
   */
  natp->suspend_state |= NACL_APP_THREAD_SUSPENDED;
  FutexWake(&natp->suspend_state, 1);

  /* Wait until we are asked to resume. */
  while (1) {
    Atomic32 state = natp->suspend_state;
    if ((state & NACL_APP_THREAD_SUSPENDED) != 0) {
      FutexWait(&natp->suspend_state, state);
      continue;  /* Retry */
    }
    break;
  }
  /*
   * Apply register modifications.  We need to use a snapshot of
   * natp->suspended_registers because, since we were asked to resume,
   * we could have been asked to suspend again, and
   * suspended_registers could have been allocated in the new
   * suspension request but not in the original suspension request.
   */
  if (suspended_registers != NULL) {
    *regs = *suspended_registers;
  }
}
示例#5
0
static void HandleUntrustedFault(int signal,
                                 struct NaClSignalContext *regs,
                                 struct NaClAppThread *natp) {
  /* Sanity check. */
  if ((natp->suspend_state & NACL_APP_THREAD_UNTRUSTED) == 0) {
    NaClSignalErrorMessage("HandleUntrustedFault: Unexpected suspend_state\n");
    NaClAbort();
  }

  /* Notify the debug stub by marking this thread as faulted. */
  natp->fault_signal = signal;
  AtomicIncrement(&natp->nap->faulted_thread_count, 1);

  /*
   * We now expect the debug stub to suspend this thread via the
   * thread suspension API.  This will allow the debug stub to get the
   * register state at the point the fault happened.  The debug stub
   * will be able to modify the register state before unblocking the
   * thread using NaClAppThreadUnblockIfFaulted().
   */
  do {
    int new_signal;
    sigset_t sigset;
    sigemptyset(&sigset);
    sigaddset(&sigset, NACL_THREAD_SUSPEND_SIGNAL);
    if (sigwait(&sigset, &new_signal) != 0) {
      NaClSignalErrorMessage("HandleUntrustedFault: sigwait() failed\n");
      NaClAbort();
    }
    if (new_signal != NACL_THREAD_SUSPEND_SIGNAL) {
      NaClSignalErrorMessage("HandleUntrustedFault: "
                             "sigwait() returned unexpected result\n");
      NaClAbort();
    }
    HandleSuspendSignal(regs);
  } while (natp->fault_signal != 0);
}