/* * Install a syscall trampoline at target_addr. NB: Thread-safe. */ void NaClPatchOneTrampolineCall(uintptr_t call_target_addr, uintptr_t target_addr) { struct NaClPatchInfo patch_info; struct NaClPatch tramp_addr; struct NaClPatch call_target; tramp_addr.target = (((uintptr_t) &NaCl_trampoline_tramp_addr) - sizeof(uint32_t)); tramp_addr.value = (uint32_t) target_addr; NaClLog(6, "call_target_addr = 0x%"NACL_PRIxPTR"\n", call_target_addr); CHECK(0 != call_target_addr); call_target.target = (((uintptr_t) &NaCl_trampoline_call_target) - sizeof(uintptr_t)); call_target.value = call_target_addr; NaClPatchInfoCtor(&patch_info); patch_info.abs64 = &call_target; patch_info.num_abs64 = 1; patch_info.abs32 = &tramp_addr; patch_info.num_abs32 = 1; patch_info.dst = target_addr; patch_info.src = (uintptr_t) &NaCl_trampoline_code; patch_info.nbytes = ((uintptr_t) &NaCl_trampoline_code_end - (uintptr_t) &NaCl_trampoline_code); CHECK(patch_info.nbytes <= NACL_INSTR_BLOCK_SIZE); NaClApplyPatchToMemory(&patch_info); }
/* * 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); }
/* * 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 call_target; uintptr_t call_target_addr; call_target_addr = nap->dispatch_thunk; NaClLog(4, "call_target_addr = 0x%"NACL_PRIxPTR"\n", call_target_addr); CHECK(0 != call_target_addr); call_target.target = (((uintptr_t) &NaCl_trampoline_call_target) - sizeof(uintptr_t)); call_target.value = call_target_addr; NaClPatchInfoCtor(&patch_info); patch_info.abs64 = &call_target; patch_info.num_abs64 = 1; patch_info.dst = target_addr; patch_info.src = (uintptr_t) &NaCl_trampoline_code; patch_info.nbytes = ((uintptr_t) &NaCl_trampoline_code_end - (uintptr_t) &NaCl_trampoline_code); NaClApplyPatchToMemory(&patch_info); }
void NaClLoadSpringboard(struct NaClApp *nap) { /* * patch in springboard.S code into space in place of * the last syscall in the trampoline region. */ struct NaClPatchInfo patch_info; nap->springboard_addr = NACL_TRAMPOLINE_END - nap->bundle_size; NaClPatchInfoCtor(&patch_info); patch_info.dst = nap->mem_start + nap->springboard_addr; patch_info.src = (uintptr_t) &NaCl_springboard; patch_info.nbytes = ((uintptr_t) &NaCl_springboard_end - (uintptr_t) &NaCl_springboard); NaClApplyPatchToMemory(&patch_info); nap->springboard_addr += NACL_HALT_LEN; /* skip the hlt */ }
/* * 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; }
int NaClMakeDispatchThunk(struct NaClApp *nap) { int retval = 0; /* fail */ int error; void *thunk_addr = NULL; struct NaClPatchInfo patch_info; struct NaClPatch jmp_target; NaClLog(LOG_WARNING, "Entered NaClMakeDispatchThunk\n"); if (0 != nap->dispatch_thunk) { NaClLog(LOG_ERROR, " dispatch_thunk already initialized!\n"); return 1; } if (0 != (error = NaCl_page_alloc_randomized(&thunk_addr, NACL_MAP_PAGESIZE))) { NaClLog(LOG_INFO, "NaClMakeDispatchThunk::NaCl_page_alloc failed, errno %d\n", -error); retval = 0; goto cleanup; } NaClLog(LOG_INFO, "NaClMakeDispatchThunk: got addr 0x%"NACL_PRIxPTR"\n", (uintptr_t) thunk_addr); if (0 != (error = NaCl_mprotect(thunk_addr, NACL_MAP_PAGESIZE, PROT_READ | PROT_WRITE))) { NaClLog(LOG_INFO, "NaClMakeDispatchThunk::NaCl_mprotect r/w failed, errno %d\n", -error); retval = 0; goto cleanup; } NaClFillMemoryRegionWithHalt(thunk_addr, NACL_MAP_PAGESIZE); jmp_target.target = (((uintptr_t) &NaClDispatchThunk_jmp_target) - sizeof(uintptr_t)); jmp_target.value = (uintptr_t) NaClSyscallSeg; NaClPatchInfoCtor(&patch_info); patch_info.abs64 = &jmp_target; patch_info.num_abs64 = 1; patch_info.dst = (uintptr_t) thunk_addr; patch_info.src = (uintptr_t) &NaClDispatchThunk; patch_info.nbytes = ((uintptr_t) &NaClDispatchThunkEnd - (uintptr_t) &NaClDispatchThunk); NaClApplyPatchToMemory(&patch_info); if (0 != (error = NaCl_mprotect(thunk_addr, NACL_MAP_PAGESIZE, PROT_EXEC|PROT_READ))) { NaClLog(LOG_INFO, "NaClMakeDispatchThunk::NaCl_mprotect r/x 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->dispatch_thunk = (uintptr_t) thunk_addr; } return retval; }