Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / service_runtime / arch / x86_32 / nacl_syscall_32.S
1 /*
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.
5  */
6
7 /*
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
13  * call handler code.
14  */
15
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"
18
19 /*
20  * on stack:
21  *
22  *  syscall-arg-N
23  *  ...
24  *  syscall-arg-1
25  *  RA for caller to libc stub
26  *  code seg from trampoline lcall
27  *  RA for trampoline lcall (used to compute syscall number)
28  */
29
30         .text
31
32         /*
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.
37          *
38          * For accessing global variables, we avoid PIC address
39          * synthesis using the usual sequence of
40          *
41          *     call 0f
42          * 0:  pop %eax
43          *
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.
48          */
49 MACRO(syscallseg)
50 MACROENTRY
51         cld
52         xor     %eax, %eax
53         movw    %gs, %ax
54         /*
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.
64          */
65         movl    %eax, %edx
66         andl    MACROIMMED(7), %edx  /* extract TI and RPL fields */
67         cmpl    MACROIMMED(7), %edx  /* make sure it's LDT, ring 3 */
68         jne     1f
69         shr     MACROIMMED(3), %eax
70         test    %eax, %eax  /* zero is illegal (and default) */
71         jz      1f
72
73         movl    (%ecx,%eax,4), %edx
74         test    %edx, %edx
75         jz      1f
76
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)
81         /*
82          * Record the value of %esp that we will restore when
83          * returning to untrusted code from the syscall.
84          */
85         leal    0xc(%esp), %ecx
86         movl    %ecx, NACL_THREAD_CONTEXT_OFFSET_STACK_PTR(%edx)
87
88         /*
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.
92          */
93         fnstcw  NACL_THREAD_CONTEXT_OFFSET_FCW(%edx)
94         fldcw   NACL_THREAD_CONTEXT_OFFSET_SYS_FCW(%edx)
95
96 .if MACROARG2
97         /*
98          * Save the SSE control word.  Then reload the system default
99          * state to use while running trusted code.
100          */
101         stmxcsr NACL_THREAD_CONTEXT_OFFSET_MXCSR(%edx)
102         ldmxcsr NACL_THREAD_CONTEXT_OFFSET_SYS_MXCSR(%edx)
103 .endif
104 DEFINE_GLOBAL_HIDDEN_LOCATION(MACROARG3): /* NaClSyscallSegRegsSaved */
105
106         /*
107          * We do not save segment registers, which untrusted code is
108          * powerless to change.
109          */
110
111         /*
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.
115          *
116          * %cs and %ds already taken care of by NaCl_trampoline_seg_code
117          *
118          * %ebx need not be saved/restored even if -fpic were used, since
119          * in that case %ebx is initialized on fn entry.
120          */
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
124
125         /* 'lss' sets %ss as well as %esp */
126         lss     NACL_THREAD_CONTEXT_OFFSET_TRUSTED_STACK_PTR(%edx), %esp
127         push    %edx
128         call    IDENTIFIER(NaClSyscallCSegHook)
129
130         /* NaClSyscallCSegHook return value is argument to NaClSwitch. */
131         push    %eax
132
133         /*
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.
137          */
138         call    __x86.get_pc_thunk.ax
139         call    *(IDENTIFIER(NaClSwitch)-.)(%eax)
140
141         /*
142          * If stack usage in the above code changes, modify initial %esp
143          * computation -- see nacl_switch_to_app.c:NaClStartThreadInApp.
144          */
145 DEFINE_GLOBAL_HIDDEN_LOCATION(MACROARG4): /* NaClSyscallThreadCaptureFault */
146 1:      hlt
147         /* noret */
148 ENDMACRO
149
150         /*
151          * Note that long lines are required here because "\" does not
152          * work in the Windows build.
153          */
154         syscallseg NaClSyscallSegNoSSE, 0, NaClSyscallSegRegsSavedNoSSE, NaClSyscallThreadCaptureFaultNoSSE
155         syscallseg NaClSyscallSegSSE, 1, NaClSyscallSegRegsSavedSSE, NaClSyscallThreadCaptureFaultSSE
156
157         /*
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.
161          */
162         .data
163 DEFINE_GLOBAL_HIDDEN_LOCATION(NaClSwitch):
164         .long 0