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