2 * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
8 * NaCl service runtime context switch code. NaClSyscallSeg is the
9 * lcall target from the syscall trampoline code, and this code is
10 * responsible for figuring out the identity of the thread, saving
11 * the user registers, finish restoring the segment registers (and
12 * getting out of the sandbox), and actually invoking the C system
16 #include "native_client/src/trusted/service_runtime/arch/x86_32/sel_rt_32.h"
17 #include "native_client/src/trusted/service_runtime/nacl_config.h"
25 * RA for caller to libc stub
26 * code seg from trampoline lcall
27 * RA for trampoline lcall (used to compute syscall number)
33 * The trampoline code calls NaClPcrelThunk using an lcall,
34 * restoring %cs. Next, NaClPcrelThunk invokes
35 * NaClSyscallSeg, with nacl_user in %ecx and %ds restored.
36 * The other segment registers remain to be restored.
38 * For accessing global variables, we avoid PIC address
39 * synthesis using the usual sequence of
44 * to get the address of the pop into a register. Such
45 * sequences are verboten in the context switch code, since we
46 * are still using a stack in untrusted memory, and we need to
47 * figure out the per-thread secure stack first.
55 * Check that the %gs value is really one that might have been
56 * assigned to a NaCl thread. This could only happen if an
57 * attacker adaptively used a NaCl module to discover the
58 * absolute addresses needed to make a syscall (%cs relative
59 * is not enough, unless it is a zero-based code memory
60 * sandbox), and use an independent code vulnerability (e.g.,
61 * in an image processing library linked into the same
62 * application embedding NaCl) to cause a trusted thread to
63 * jump into this code.
66 andl MACROIMMED(7), %edx /* extract TI and RPL fields */
67 cmpl MACROIMMED(7), %edx /* make sure it's LDT, ring 3 */
69 shr MACROIMMED(3), %eax
70 test %eax, %eax /* zero is illegal (and default) */
73 movl (%ecx,%eax,4), %edx
77 movl %ebx, NACL_THREAD_CONTEXT_OFFSET_EBX(%edx)
78 movl %esi, NACL_THREAD_CONTEXT_OFFSET_ESI(%edx)
79 movl %edi, NACL_THREAD_CONTEXT_OFFSET_EDI(%edx)
80 movl %ebp, NACL_THREAD_CONTEXT_OFFSET_FRAME_PTR(%edx)
82 * Record the value of %esp that we will restore when
83 * returning to untrusted code from the syscall.
86 movl %ecx, NACL_THREAD_CONTEXT_OFFSET_STACK_PTR(%edx)
89 * Save the x87 FPU control word. This is callee-saved,
90 * while all other x87 state is caller-saved. Then reload
91 * the system default state to use while running trusted code.
93 fnstcw NACL_THREAD_CONTEXT_OFFSET_FCW(%edx)
94 fldcw NACL_THREAD_CONTEXT_OFFSET_SYS_FCW(%edx)
98 * Save the SSE control word. Then reload the system default
99 * state to use while running trusted code.
101 stmxcsr NACL_THREAD_CONTEXT_OFFSET_MXCSR(%edx)
102 ldmxcsr NACL_THREAD_CONTEXT_OFFSET_SYS_MXCSR(%edx)
104 DEFINE_GLOBAL_HIDDEN_LOCATION(MACROARG3): /* NaClSyscallSegRegsSaved */
107 * We do not save segment registers, which untrusted code is
108 * powerless to change.
112 * load only the system segments; called code do not depend on
113 * any registers having particular values. we will clear/discard
114 * caller-saved registers at system call return.
116 * %cs and %ds already taken care of by NaCl_trampoline_seg_code
118 * %ebx need not be saved/restored even if -fpic were used, since
119 * in that case %ebx is initialized on fn entry.
121 movw NACL_THREAD_CONTEXT_OFFSET_TRUSTED_ES(%edx), %es
122 movw NACL_THREAD_CONTEXT_OFFSET_TRUSTED_FS(%edx), %fs
123 movw NACL_THREAD_CONTEXT_OFFSET_TRUSTED_GS(%edx), %gs
125 /* 'lss' sets %ss as well as %esp */
126 lss NACL_THREAD_CONTEXT_OFFSET_TRUSTED_STACK_PTR(%edx), %esp
128 call IDENTIFIER(NaClSyscallCSegHook)
130 /* NaClSyscallCSegHook return value is argument to NaClSwitch. */
134 * Now switch back to untrusted code. This does not return.
135 * The first call is standard PIC magic.
136 * See nacl_switch_32.S for the definition.
138 call __x86.get_pc_thunk.ax
139 call *(IDENTIFIER(NaClSwitch)-.)(%eax)
142 * If stack usage in the above code changes, modify initial %esp
143 * computation -- see nacl_switch_to_app.c:NaClStartThreadInApp.
145 DEFINE_GLOBAL_HIDDEN_LOCATION(MACROARG4): /* NaClSyscallThreadCaptureFault */
151 * Note that long lines are required here because "\" does not
152 * work in the Windows build.
154 syscallseg NaClSyscallSegNoSSE, 0, NaClSyscallSegRegsSavedNoSSE, NaClSyscallThreadCaptureFaultNoSSE
155 syscallseg NaClSyscallSegSSE, 1, NaClSyscallSegRegsSavedSSE, NaClSyscallThreadCaptureFaultSSE
158 * This is defined here rather than in C because the assembler for
159 * MacOS cannot handle the PC-relative reference above unless the
160 * symbol is defined in the same file.
163 DEFINE_GLOBAL_HIDDEN_LOCATION(NaClSwitch):