예제 #1
0
int NaClMachThreadStateIsInUntrusted(x86_thread_state_t *state,
                                     size_t nacl_thread_index) {
#if NACL_BUILD_SUBARCH == 32

  uint16_t global_cs;

  UNREFERENCED_PARAMETER(nacl_thread_index);

  CHECK(state->tsh.flavor == x86_THREAD_STATE32);

  global_cs = NaClGetGlobalCs();

  /*
   * If global_cs is 0 (which is not a usable segment selector), the
   * sandbox has not been initialised yet, so there can be no untrusted
   * code running.
   */
  if (global_cs == 0) {
    return 0;
  }

  return state->uts.ts32.__cs != global_cs;

#elif NACL_BUILD_SUBARCH == 64

  struct NaClAppThread *natp;

  CHECK(state->tsh.flavor == x86_THREAD_STATE64);

  natp = NaClAppThreadGetFromIndex(nacl_thread_index);
  return NaClIsUserAddr(natp->nap, state->uts.ts64.__rip);

#endif  /* NACL_BUILD_SUBARCH */
}
/*
 * Install a syscall trampoline at target_addr.  PIC version.
 */
void  NaClPatchOneTrampoline(struct NaClApp *nap,
                             uintptr_t      target_addr) {
  struct NaClPatchInfo  patch_info;
  struct NaClPatch      patch32[1];
  struct NaClPatch      patch16[1];

  UNREFERENCED_PARAMETER(nap);

  patch16[0].target = ((uintptr_t) &NaCl_tramp_cseg_patch) - 2;
  patch16[0].value = NaClGetGlobalCs();

  patch32[0].target = ((uintptr_t) &NaCl_tramp_cseg_patch) - 6;
  patch32[0].value = (uintptr_t) nap->pcrel_thunk;

  NaClPatchInfoCtor(&patch_info);

  patch_info.abs16 = patch16;
  patch_info.num_abs16 = NACL_ARRAY_SIZE(patch16);

  patch_info.abs32 = patch32;
  patch_info.num_abs32 = NACL_ARRAY_SIZE(patch32);;

  patch_info.dst = target_addr;
  patch_info.src = (uintptr_t) &NaCl_trampoline_seg_code;
  patch_info.nbytes = ((uintptr_t) &NaCl_trampoline_seg_end
                       - (uintptr_t) &NaCl_trampoline_seg_code);

  NaClApplyPatchToMemory(&patch_info);
}
void NaClAppThreadGetSuspendedRegistersInternal(
    struct NaClAppThread *natp, struct NaClSignalContext *regs) {
#if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
  /*
   * We might have suspended the thread while it is returning to
   * untrusted code via NaClSwitchRemainingRegsViaECX() and
   * NaCl_springboard_all_regs.  This is particularly likely for a
   * faulted thread that has been resumed and suspended again without
   * ever being unblocked by NaClAppThreadUnblockIfFaulted().
   *
   * In this situation, we must undo the register state modifications
   * made by NaClAppThreadSetSuspendedRegistersInternal().
   */
  struct NaClAppThreadSuspendedRegisters *state = natp->suspended_registers;
  struct NaClApp *nap = natp->nap;
  uint32_t eip = state->context.uts.ts32.__eip;
  if ((state->context.uts.ts32.__cs == NaClGetGlobalCs() &&
       eip >= (uintptr_t) NaClSwitchRemainingRegsViaECX &&
       eip < (uintptr_t) NaClSwitchRemainingRegsAsmEnd) ||
      (state->context.uts.ts32.__cs == natp->user.cs &&
       eip >= nap->all_regs_springboard.start_addr &&
       eip < nap->all_regs_springboard.end_addr)) {
    state->context.uts.ts32.__eip = natp->user.gs_segment.new_prog_ctr;
    state->context.uts.ts32.__ecx = natp->user.gs_segment.new_ecx;
    /*
     * It is sometimes necessary to restore the following registers
     * too, depending on how far we are through
     * NaClSwitchRemainingRegsViaECX().
     */
    state->context.uts.ts32.__cs = natp->user.cs;
    state->context.uts.ts32.__ds = natp->user.ds;
    state->context.uts.ts32.__es = natp->user.es;
    state->context.uts.ts32.__fs = natp->user.fs;
    state->context.uts.ts32.__gs = natp->user.gs;
    state->context.uts.ts32.__ss = natp->user.ss;
  }
#endif

  NaClSignalContextFromMacThreadState(regs,
                                      &natp->suspended_registers->context);
}
void NaClAppThreadSetSuspendedRegistersInternal(
    struct NaClAppThread *natp, const struct NaClSignalContext *regs) {
  kern_return_t result;
  mach_msg_type_number_t size;
  struct NaClAppThreadSuspendedRegisters *state = natp->suspended_registers;
  x86_thread_state_t context_copy;

  NaClSignalContextToMacThreadState(&state->context, regs);
  context_copy = state->context;

#if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
  /*
   * thread_set_state() ignores the %cs value we supply and always
   * resets %cs back to the trusted-code value.  This means we must
   * set up the new untrusted register state via a trusted code
   * routine which returns to untrusted code via a springboard.
   *
   * We reset %cs here in case the Mac kernel is ever fixed to not
   * ignore the supplied %cs value.
   */
  context_copy.uts.ts32.__cs = NaClGetGlobalCs();
  context_copy.uts.ts32.__ds = NaClGetGlobalDs();
  /* Reset these too just in case. */
  context_copy.uts.ts32.__es = NaClGetGlobalDs();
  context_copy.uts.ts32.__ss = NaClGetGlobalDs();
  context_copy.uts.ts32.__ecx = (uintptr_t) &state->switch_state;
  context_copy.uts.ts32.__eip = (uintptr_t) NaClSwitchRemainingRegsViaECX;
  NaClSwitchRemainingRegsSetup(&state->switch_state, natp, regs);
#endif

  size = sizeof(context_copy) / sizeof(natural_t);
  result = thread_set_state(GetHostThreadPort(natp), x86_THREAD_STATE,
                            (void *) &context_copy, size);
  if (result != KERN_SUCCESS) {
    NaClLog(LOG_FATAL, "NaClAppThreadSetSuspendedRegistersInternal: "
            "thread_set_state() call failed: error %d\n", result);
  }
}