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); } }