/* * Install a syscall trampoline at target_addr. NB: Thread-safe. */ void NaClPatchOneTrampoline(struct NaClApp *nap, uintptr_t target_addr) { struct NaClPatchInfo patch_info; struct NaClPatch patch16[1]; struct NaClPatch patch32[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_dseg_patch) - 4; patch32[0].value = NaClGetGlobalDs(); /* opens the data sandbox */ 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 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); } }
/* * Create thunk for use by syscall trampoline code. */ int NaClMakePcrelThunk(struct NaClApp *nap) { int retval = 0; /* fail */ int error; void *thunk_addr = NULL; struct NaClPatchInfo patch_info; uintptr_t patch_rel32[1]; /* NaClSyscallSeg */ struct NaClPatch patch_abs32[2]; /* ds, nacl_user */ /* idempotent */ nacl_pcrel_globals.user = nacl_user; nacl_pcrel_globals.sys = nacl_sys; if (0 != (error = NaCl_page_alloc(&thunk_addr, NACL_MAP_PAGESIZE))) { NaClLog(LOG_INFO, "NaClMakePcrelThunk::NaCl_page_alloc failed, errno %d\n", -error); retval = 0; goto cleanup; } patch_rel32[0] = ((uintptr_t) &NaClPcrelThunk_end) - 4; patch_abs32[0].target = ((uintptr_t) &NaClPcrelThunk_dseg_patch) - 4; patch_abs32[0].value = NaClGetGlobalDs(); patch_abs32[1].target = ((uintptr_t) &NaClPcrelThunk_globals_patch) - 4; patch_abs32[1].value = (uintptr_t) &nacl_pcrel_globals; NaClPatchInfoCtor(&patch_info); patch_info.rel32 = patch_rel32; patch_info.num_rel32 = NACL_ARRAY_SIZE(patch_rel32); patch_info.abs32 = patch_abs32; patch_info.num_abs32 = NACL_ARRAY_SIZE(patch_abs32); patch_info.dst = (uintptr_t) thunk_addr; patch_info.src = (uintptr_t) &NaClPcrelThunk; patch_info.nbytes = ((uintptr_t) &NaClPcrelThunk_end - (uintptr_t) &NaClPcrelThunk); NaClApplyPatchToMemory(&patch_info); if (0 != (error = NaCl_mprotect(thunk_addr, NACL_MAP_PAGESIZE, PROT_EXEC|PROT_READ))) { NaClLog(LOG_INFO, "NaClMakePcrelThunk::NaCl_mprotect failed, errno %d\n", -error); retval = 0; goto cleanup; } retval = 1; cleanup: if (0 == retval) { if (NULL != thunk_addr) { NaCl_page_free(thunk_addr, NACL_MAP_PAGESIZE); thunk_addr = NULL; } } else { nap->pcrel_thunk = (uintptr_t) thunk_addr; } return retval; }