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 run-time.
9 */
10
11 #include "native_client/src/include/portability.h"
12
13 #include <errno.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <time.h>
17
18 #include "native_client/src/include/nacl_compiler_annotations.h"
19 #include "native_client/src/shared/platform/nacl_exit.h"
20 #include "native_client/src/shared/platform/nacl_log.h"
21 #include "native_client/src/trusted/service_runtime/nacl_globals.h"
22 #include "native_client/src/trusted/service_runtime/nacl_config.h"
23 #include "native_client/src/trusted/service_runtime/nacl_copy.h"
24 #include "native_client/src/trusted/service_runtime/nacl_switch_to_app.h"
25 #include "native_client/src/trusted/service_runtime/nacl_syscall_handlers.h"
26 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
27 #include "native_client/src/trusted/service_runtime/sel_rt.h"
28
29 #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
30 #include "native_client/src/trusted/service_runtime/include/bits/nacl_syscalls.h"
31 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
32 #include "native_client/src/trusted/service_runtime/nacl_stack_safety.h"
33
34
35 /*
36 * HandleStackContext() fetches some of the inputs to the NaCl syscall
37 * from the untrusted stack. It updates NaClThreadContext so that the
38 * saved state will be complete in case this state is read via the
39 * thread suspension API.
40 *
41 * This is called while natp->suspend_state is set to
42 * NACL_APP_THREAD_UNTRUSTED, which has two consequences:
43 *
44 * 1) We may read untrusted address space without calling
45 * NaClCopyTakeLock() first, because this function's execution
46 * will be suspended while any mmap hole is opened up on Windows.
47 *
48 * 2) We may not claim any locks. This means we may not call
49 * NaClLog(). (An exception is that LOG_FATAL calls to NaClLog()
50 * should be okay for internal errors.)
51 */
HandleStackContext(struct NaClAppThread * natp,uint32_t * tramp_ret_out,uintptr_t * sp_user_out)52 static void HandleStackContext(struct NaClAppThread *natp,
53 uint32_t *tramp_ret_out,
54 uintptr_t *sp_user_out) {
55 struct NaClApp *nap = natp->nap;
56 uintptr_t sp_user;
57 uintptr_t sp_sys;
58 uint32_t tramp_ret;
59 nacl_reg_t user_ret;
60
61 /*
62 * sp_sys points to the top of the user stack where return addresses
63 * and syscall arguments are stored.
64 *
65 * Note that on x86-64, NaClUserToSysStackAddr() and
66 * NaClSysToUserStackAddr() do no range check. sp_user must be okay
67 * for control to have reached here, because nacl_syscall*.S writes
68 * to the stack.
69 */
70 sp_user = NaClGetThreadCtxSp(&natp->user);
71 sp_sys = NaClUserToSysStackAddr(nap, sp_user);
72 /*
73 * Get the trampoline return address. This just tells us which
74 * trampoline was called (and hence the syscall number); we never
75 * return to the trampoline.
76 */
77 tramp_ret = *(volatile uint32_t *) (sp_sys + NACL_TRAMPRET_FIX);
78 /*
79 * Get the user return address (where we return to after the system
80 * call). We must ensure the address is properly sandboxed before
81 * switching back to untrusted code.
82 */
83 user_ret = *(volatile uintptr_t *) (sp_sys + NACL_USERRET_FIX);
84 user_ret = (nacl_reg_t) NaClSandboxCodeAddr(nap, (uintptr_t) user_ret);
85 natp->user.new_prog_ctr = user_ret;
86
87 *tramp_ret_out = tramp_ret;
88 *sp_user_out = sp_user;
89 }
90
NaClSyscallCSegHook(struct NaClThreadContext * ntcp)91 struct NaClThreadContext *NaClSyscallCSegHook(struct NaClThreadContext *ntcp) {
92 struct NaClAppThread *natp = NaClAppThreadFromThreadContext(ntcp);
93 struct NaClApp *nap;
94 uint32_t tramp_ret;
95 size_t sysnum;
96 uintptr_t sp_user;
97 uint32_t sysret;
98
99 /*
100 * Mark the thread as running on a trusted stack as soon as possible
101 * so that we can report any crashes that occur after this point.
102 */
103 NaClStackSafetyNowOnTrustedStack();
104
105 HandleStackContext(natp, &tramp_ret, &sp_user);
106
107 /*
108 * Before this call, the thread could be suspended, so we should not
109 * lock any mutexes before this, otherwise it could cause a
110 * deadlock.
111 */
112 NaClAppThreadSetSuspendState(natp, NACL_APP_THREAD_UNTRUSTED,
113 NACL_APP_THREAD_TRUSTED);
114
115 nap = natp->nap;
116
117 NaClCopyTakeLock(nap);
118 /*
119 * held until syscall args are copied, which occurs in the generated
120 * code.
121 */
122
123 sysnum = (tramp_ret - NACL_SYSCALL_START_ADDR) >> NACL_SYSCALL_BLOCK_SHIFT;
124
125 NaClLog(4, "Entering syscall %"NACL_PRIuS
126 ": return address 0x%08"NACL_PRIxNACL_REG"\n",
127 sysnum, natp->user.new_prog_ctr);
128
129 /*
130 * usr_syscall_args is used by Decoder functions in
131 * nacl_syscall_handlers.c which is automatically generated file and
132 * placed in the
133 * scons-out/.../gen/native_client/src/trusted/service_runtime/
134 * directory. usr_syscall_args must point to the first argument of
135 * a system call. System call arguments are placed on the untrusted
136 * user stack.
137 *
138 * We save the user address for user syscall arguments fetching and
139 * for VM range locking.
140 */
141 natp->usr_syscall_args = NaClRawUserStackAddrNormalize(sp_user +
142 NACL_SYSARGS_FIX);
143
144 if (NACL_UNLIKELY(sysnum >= NACL_MAX_SYSCALLS)) {
145 NaClLog(2, "INVALID system call %"NACL_PRIuS"\n", sysnum);
146 sysret = (uint32_t) -NACL_ABI_EINVAL;
147 NaClCopyDropLock(nap);
148 } else {
149 sysret = (*(nap->syscall_table[sysnum].handler))(natp);
150 /* Implicitly drops lock */
151 }
152 NaClLog(4,
153 ("Returning from syscall %"NACL_PRIuS": return value %"NACL_PRId32
154 " (0x%"NACL_PRIx32")\n"),
155 sysnum, sysret, sysret);
156 natp->user.sysret = sysret;
157
158 /*
159 * After this NaClAppThreadSetSuspendState() call, we should not
160 * claim any mutexes, otherwise we risk deadlock.
161 */
162 NaClAppThreadSetSuspendState(natp, NACL_APP_THREAD_TRUSTED,
163 NACL_APP_THREAD_UNTRUSTED);
164 NaClStackSafetyNowOnUntrustedStack();
165
166 /*
167 * The caller switches back to untrusted code after this return.
168 */
169 return ntcp;
170 }
171