/*
 * 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);
}
Example #3
0
/*
 * 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;
}
Example #6
0
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;
}