Beispiel #1
0
/* switch to the nacl module (untrusted content) */
NORETURN void NaClSwitchToApp(struct NaClApp *nap, nacl_reg_t new_prog_ctr)
{
  nacl_user->new_prog_ctr = new_prog_ctr;
  nacl_user->sysret = nap->sysret;

  NaClSwitch(nacl_user);
}
/* switch to the nacl module (untrusted content) after signal */
NORETURN void NaClSwitchToAppAfterSignal(struct NaClApp *nap)
{
  /* prevent rdtsc execution */
  ZLOGFAIL(prctl(PR_SET_TSC, PR_TSC_SIGSEGV) == -1,
      errno, "cannot prevent rdtsc execution");

  NaClSwitch(nacl_user);
}
NORETURN void NaClStartThreadInApp(struct NaClAppThread *natp,
                                   nacl_reg_t           new_prog_ctr) {
  struct NaClApp            *nap;
  struct NaClThreadContext  *context;

#if !NACL_WINDOWS
  /*
   * Ensure stack alignment.  Stack pointer must be -8 mod 16 when no
   * __m256 objects are passed (8 mod 32 if __m256), after the call.
   * Note the current doc (as of 2009-12-09) at
   *
   *   http://www.x86-64.org/documentation/abi.pdf
   *
   * is wrong since it claims (%rsp-8) should be 0 mod 16 or mod 32
   * after the call, and it should be (%rsp+8) == 0 mod 16 or 32.
   * Clearly it makes no difference since -8 and 8 are the same mod
   * 16, but there is a difference when mod 32.
   *
   * This is not suitable for Windows because we do not reserve 32
   * bytes for the shadow space.
   */
  nacl_reg_t  secure_stack_ptr = NaClGetStackPtr();

  NaClLog(6,
          "NaClStartThreadInApp: secure stack:   0x%"NACL_PRIxNACL_REG"\n",
          secure_stack_ptr);
  secure_stack_ptr = secure_stack_ptr & ~0x1f;
  NaClLog(6,
          "NaClStartThreadInApp: adjusted stack: 0x%"NACL_PRIxNACL_REG"\n",
          secure_stack_ptr);

  natp->user.trusted_stack_ptr = secure_stack_ptr;
#endif

  nap = natp->nap;
  context = &natp->user;
  context->new_prog_ctr = new_prog_ctr;
  context->sysret = 0;
  context->r15 = nap->mem_start;

  NaClLog(6,
          "NaClStackThreadInApp: user stack: 0x%"NACL_PRIxPTR"\n",
          NaClGetThreadCtxSp(context));
  NaClLog(6,
          "NaClStartThreadInApp: switching to untrusted code\n");

#if NACL_WINDOWS
  /* This sets up a stack containing a return address that has unwind info. */
  NaClSwitchSavingStackPtr(context, &context->trusted_stack_ptr);
#else
  NaClSwitch(context);
#endif
}
/* switch to the nacl module (untrusted content) */
NORETURN void NaClSwitchToApp(struct NaClApp *nap, nacl_reg_t new_prog_ctr)
{
  nacl_user->new_prog_ctr = new_prog_ctr;
  nacl_user->sysret = nap->sysret;

#ifdef DISABLE_RDTSC
  /* prevent rdtsc execution */
  ZLOGFAIL(prctl(PR_SET_TSC, PR_TSC_SIGSEGV) == -1,
      errno, "cannot prevent rdtsc execution");
#endif

  NaClSwitch(nacl_user);
}
NORETURN void NaClStartThreadInApp(struct NaClAppThread *natp,
                                   nacl_reg_t           new_prog_ctr) {
  struct NaClApp            *nap;
  struct NaClThreadContext  *context;
  /*
   * Save service runtime segment registers; fs/gs is used for TLS
   * on Windows and Linux respectively, so will change.  The others
   * should be global, but we save them from the thread anyway.
   *
   * %cs and %ds are restored by trampoline code, so not saved here.
   */
  natp->user.trusted_es = NaClGetEs();
  natp->user.trusted_fs = NaClGetFs();
#if NACL_WINDOWS
  /*
   * Win32 leaks %gs values on return from a windows syscall if the
   * previously running thread had a non-zero %gs, e.g., an untrusted
   * thread was interrupted by the scheduler.  If we used NaClGetGs()
   * here, then in the trampoline context switch code, we will try to
   * restore %gs to this leaked value, possibly generating a fault
   * since that segment selector may not be valid (e.g., if that
   * earlier thread had exited and its selector had been deallocated).
   */
  natp->user.trusted_gs = 0;
#else
  natp->user.trusted_gs = NaClGetGs();
#endif
  natp->user.trusted_ss = NaClGetSs();
  /*
   * Preserves stack alignment.  The trampoline code loads this value
   * to %esp, then pushes the thread ID (LDT index) onto the stack as
   * argument to NaClSyscallCSegHook.  See nacl_syscall.S.
   */
  natp->user.trusted_stack_ptr = (NaClGetStackPtr() & ~0xf) + 4;

  nap = natp->nap;
  context = &natp->user;
  context->spring_addr = nap->syscall_return_springboard.start_addr;
  context->new_prog_ctr = new_prog_ctr;
  context->sysret = 0; /* %eax not used to return */

  NaClSwitch(context);
}
NORETURN void NaClStartThreadInApp(struct NaClAppThread *natp,
                                   uint32_t             new_prog_ctr) {
  struct NaClThreadContext  *context;

  natp->user.trusted_stack_ptr = NaClGetStackPtr() & ~0xf;

  context = &natp->user;
  context->new_prog_ctr = new_prog_ctr;

  /*
   * At startup this is not the return value, but the first argument.
   * In the initial thread, it gets the pointer to the information
   * block on the stack.  Additional threads do not expect anything in
   * particular in the first argument register, so we don't bother to
   * conditionalize this.
   */
  context->sysret = context->stack_ptr;

  NaClSwitch(context);
}
/*
 * syscall return
 */
NORETURN void NaClSwitchToApp(struct NaClAppThread *natp) {
  NaClSwitch(&natp->user);
}