Exemplo n.º 1
0
/*
 * d'b: alternative mechanism to pass control to user side
 * note: initializes "nacl_user" global
 */
NORETURN void SwitchToApp(struct NaClApp  *nap, uintptr_t stack_ptr)
{
  /* initialize "nacl_user" global */
  if(!nacl_user) nacl_user = malloc(sizeof(*nacl_user));
  assert(nacl_user != NULL);

  /* construct "nacl_user" global */
  NaClThreadContextCtor(nacl_user, nap, nap->initial_entry_pt,
                        NaClSysToUserStackAddr(nap, stack_ptr), 0);
  assert(NaClSignalStackAllocate(&nap->signal_stack));
  nacl_user->sysret = nap->break_addr;
  nacl_user->prog_ctr = NaClUserToSys(nap, nap->initial_entry_pt);
  nacl_user->new_prog_ctr = NaClUserToSys(nap, nap->initial_entry_pt);

  /* initialize "nacl_sys" global */
  if(!nacl_sys) nacl_sys = malloc(sizeof(*nacl_sys));
  assert(nacl_sys != NULL);
  nacl_sys->rbp = NaClGetStackPtr();
  nacl_sys->rsp = NaClGetStackPtr();

  /* set global nap to current nap object */
  gnap = nap;

  /*
   * todo: put here switch to chose proper function: avx or sse
   */
  NaClSwitchSSE(nacl_user);

  /* unreachable */
}
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
}
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);
}