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 : #include <errno.h>
8 : #include <signal.h>
9 : #include <stddef.h>
10 : #include <string.h>
11 :
12 : #include "native_client/src/include/nacl_macros.h"
13 : #include "native_client/src/include/portability_io.h"
14 : #include "native_client/src/shared/platform/nacl_check.h"
15 : #include "native_client/src/shared/platform/nacl_exit.h"
16 : #include "native_client/src/shared/platform/nacl_log.h"
17 : #include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h"
18 : #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
19 : #include "native_client/src/trusted/service_runtime/nacl_config.h"
20 : #include "native_client/src/trusted/service_runtime/nacl_exception.h"
21 : #include "native_client/src/trusted/service_runtime/nacl_globals.h"
22 : #include "native_client/src/trusted/service_runtime/nacl_signal.h"
23 : #include "native_client/src/trusted/service_runtime/nacl_tls.h"
24 : #include "native_client/src/trusted/service_runtime/sel_ldr.h"
25 : #include "native_client/src/trusted/service_runtime/sel_rt.h"
26 : #include "native_client/src/trusted/service_runtime/thread_suspension.h"
27 :
28 :
29 : /*
30 : * This module is based on the Posix signal model. See:
31 : * http://www.opengroup.org/onlinepubs/009695399/functions/sigaction.html
32 : */
33 :
34 : /*
35 : * The signals listed here should either be handled by NaCl (or otherwise
36 : * trusted code).
37 : */
38 : static int s_Signals[] = {
39 : #if NACL_ARCH(NACL_BUILD_ARCH) != NACL_mips
40 : /* This signal does not exist on MIPS. */
41 : SIGSTKFLT,
42 : #endif
43 : SIGSYS, /* Used to support a seccomp-bpf sandbox. */
44 : NACL_THREAD_SUSPEND_SIGNAL,
45 : SIGINT, SIGQUIT, SIGILL, SIGTRAP, SIGBUS, SIGFPE, SIGSEGV,
46 : /* Handle SIGABRT in case someone sends it asynchronously using kill(). */
47 : SIGABRT
48 : };
49 :
50 : static struct sigaction s_OldActions[NACL_ARRAY_SIZE_UNSAFE(s_Signals)];
51 :
52 : static NaClSignalHandler g_handler_func;
53 :
54 2 : void NaClSignalHandlerSet(NaClSignalHandler func) {
55 2 : g_handler_func = func;
56 2 : }
57 :
58 : /*
59 : * Returns, via is_untrusted, whether the signal happened while
60 : * executing untrusted code.
61 : *
62 : * Returns, via result_thread, the NaClAppThread that untrusted code
63 : * was running in.
64 : *
65 : * Note that this should only be called from the thread in which the
66 : * signal occurred, because on x86-64 it reads a thread-local variable
67 : * (nacl_current_thread).
68 : */
69 292091 : static void GetCurrentThread(const struct NaClSignalContext *sig_ctx,
70 : int *is_untrusted,
71 : struct NaClAppThread **result_thread) {
72 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
73 : /*
74 : * For x86-32, if %cs does not match, it is untrusted code.
75 : *
76 : * Note that this check might not be valid on Mac OS X, because
77 : * thread_get_state() does not return the value of NaClGetGlobalCs()
78 : * for a thread suspended inside a syscall. However, this code is
79 : * not used on Mac OS X.
80 : */
81 : *is_untrusted = (NaClGetGlobalCs() != sig_ctx->cs);
82 : *result_thread = NaClAppThreadGetFromIndex(sig_ctx->gs >> 3);
83 : #elif (NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64) || \
84 : NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm || \
85 : NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
86 292091 : struct NaClAppThread *natp = NaClTlsGetCurrentThread();
87 292091 : if (natp == NULL) {
88 1 : *is_untrusted = 0;
89 1 : *result_thread = NULL;
90 : } else {
91 : /*
92 : * Get the address of an arbitrary local, stack-allocated variable,
93 : * just for the purpose of doing a sanity check.
94 : */
95 292090 : void *pointer_into_stack = &natp;
96 : /*
97 : * Sanity check: Make sure the stack we are running on is not
98 : * allocated in untrusted memory. This checks that the alternate
99 : * signal stack is correctly set up, because otherwise, if it is
100 : * not set up, the test case would not detect that.
101 : *
102 : * There is little point in doing a CHECK instead of a DCHECK,
103 : * because if we are running off an untrusted stack, we have already
104 : * lost.
105 : */
106 292090 : DCHECK(!NaClIsUserAddr(natp->nap, (uintptr_t) pointer_into_stack));
107 292090 : *is_untrusted = NaClIsUserAddr(natp->nap, sig_ctx->prog_ctr);
108 292090 : *result_thread = natp;
109 : }
110 : #else
111 : # error Unsupported architecture
112 : #endif
113 :
114 : /*
115 : * Trusted code could accidentally jump into sandbox address space,
116 : * so don't rely on prog_ctr on its own for determining whether a
117 : * crash comes from untrusted code. We don't want to restore
118 : * control to an untrusted exception handler if trusted code
119 : * crashes.
120 : */
121 568172 : if (*is_untrusted &&
122 276081 : ((*result_thread)->suspend_state & NACL_APP_THREAD_UNTRUSTED) == 0) {
123 0 : *is_untrusted = 0;
124 : }
125 292091 : }
126 :
127 2 : static void FindAndRunHandler(int sig, siginfo_t *info, void *uc) {
128 : unsigned int a;
129 :
130 : /* If we need to keep searching, try the old signal handler. */
131 20 : for (a = 0; a < NACL_ARRAY_SIZE(s_Signals); a++) {
132 : /* If we handle this signal */
133 20 : if (s_Signals[a] == sig) {
134 : /* If this is a real sigaction pointer... */
135 2 : if ((s_OldActions[a].sa_flags & SA_SIGINFO) != 0) {
136 : /*
137 : * On Mac OS X, sigaction() can return a "struct sigaction"
138 : * with SA_SIGINFO set but with a NULL sa_sigaction if no
139 : * signal handler was previously registered. This is allowed
140 : * by POSIX, which does not require a struct returned by
141 : * sigaction() to be intelligible. We check for NULL here to
142 : * avoid a crash.
143 : */
144 0 : if (s_OldActions[a].sa_sigaction != NULL) {
145 : /* then call the old handler. */
146 0 : s_OldActions[a].sa_sigaction(sig, info, uc);
147 0 : break;
148 : }
149 : } else {
150 : /* otherwise check if it is a real signal pointer */
151 2 : if ((s_OldActions[a].sa_handler != SIG_DFL) &&
152 0 : (s_OldActions[a].sa_handler != SIG_IGN)) {
153 : /* and call the old signal. */
154 0 : s_OldActions[a].sa_handler(sig);
155 0 : break;
156 : }
157 : }
158 : /*
159 : * We matched the signal, but didn't handle it, so we emulate
160 : * the default behavior which is to exit the app with the signal
161 : * number as the error code.
162 : */
163 2 : NaClExit(-sig);
164 : }
165 : }
166 0 : }
167 :
168 : /*
169 : * This function checks whether we can dispatch the signal to an
170 : * untrusted exception handler. If we can, it modifies the register
171 : * state to call the handler and writes a stack frame into into
172 : * untrusted address space, and returns true. Otherwise, it returns
173 : * false.
174 : */
175 266383 : static int DispatchToUntrustedHandler(struct NaClAppThread *natp,
176 : struct NaClSignalContext *regs) {
177 266383 : struct NaClApp *nap = natp->nap;
178 : uintptr_t frame_addr;
179 : volatile struct NaClExceptionFrame *frame;
180 : uint32_t new_stack_ptr;
181 : uintptr_t context_user_addr;
182 :
183 266383 : if (!NaClSignalCheckSandboxInvariants(regs, natp)) {
184 0 : return 0;
185 : }
186 266383 : if (nap->exception_handler == 0) {
187 8 : return 0;
188 : }
189 266375 : if (natp->exception_flag) {
190 1 : return 0;
191 : }
192 :
193 266374 : natp->exception_flag = 1;
194 :
195 266374 : if (natp->exception_stack == 0) {
196 266333 : new_stack_ptr = regs->stack_ptr - NACL_STACK_RED_ZONE;
197 : } else {
198 41 : new_stack_ptr = natp->exception_stack;
199 : }
200 : /* Allocate space for the stack frame, and ensure its alignment. */
201 266374 : new_stack_ptr -=
202 : sizeof(struct NaClExceptionFrame) - NACL_STACK_PAD_BELOW_ALIGN;
203 266374 : new_stack_ptr = new_stack_ptr & ~NACL_STACK_ALIGN_MASK;
204 266374 : new_stack_ptr -= NACL_STACK_ARGS_SIZE;
205 266374 : new_stack_ptr -= NACL_STACK_PAD_BELOW_ALIGN;
206 266374 : frame_addr = NaClUserToSysAddrRange(nap, new_stack_ptr,
207 : sizeof(struct NaClExceptionFrame));
208 266374 : if (frame_addr == kNaClBadAddress) {
209 : /* We cannot write the stack frame. */
210 0 : return 0;
211 : }
212 266374 : context_user_addr = new_stack_ptr + offsetof(struct NaClExceptionFrame,
213 : context);
214 :
215 266374 : frame = (struct NaClExceptionFrame *) frame_addr;
216 266374 : NaClSignalSetUpExceptionFrame(frame, regs, context_user_addr);
217 :
218 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
219 : regs->prog_ctr = nap->exception_handler;
220 : regs->stack_ptr = new_stack_ptr;
221 : #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64
222 266374 : regs->rdi = context_user_addr; /* Argument 1 */
223 266374 : regs->prog_ctr = NaClUserToSys(nap, nap->exception_handler);
224 266374 : regs->stack_ptr = NaClUserToSys(nap, new_stack_ptr);
225 : #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
226 : /*
227 : * Returning from the exception handler is not possible, so to avoid
228 : * any confusion that might arise from jumping to an uninitialised
229 : * address, we set the return address to zero.
230 : */
231 : regs->lr = 0;
232 : regs->r0 = context_user_addr; /* Argument 1 */
233 : regs->prog_ctr = NaClUserToSys(nap, nap->exception_handler);
234 : regs->stack_ptr = NaClUserToSys(nap, new_stack_ptr);
235 : #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
236 : regs->return_addr = 0;
237 : regs->a0 = context_user_addr;
238 : regs->prog_ctr = NaClUserToSys(nap, nap->exception_handler);
239 : regs->stack_ptr = NaClUserToSys(nap, new_stack_ptr);
240 : /*
241 : * Per Linux/MIPS convention, PIC functions assume that t9 holds
242 : * the function's address on entry.
243 : */
244 : regs->t9 = regs->prog_ctr;
245 : #else
246 : # error Unsupported architecture
247 : #endif
248 :
249 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
250 266374 : regs->flags &= ~NACL_X86_DIRECTION_FLAG;
251 : #endif
252 :
253 266374 : return 1;
254 : }
255 :
256 292091 : static void SignalCatch(int sig, siginfo_t *info, void *uc) {
257 : struct NaClSignalContext sig_ctx;
258 : int is_untrusted;
259 : struct NaClAppThread *natp;
260 :
261 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
262 : /*
263 : * Reset the x86 direction flag. New versions of gcc and libc
264 : * assume that the direction flag is clear on entry to a function,
265 : * as the x86 ABI requires. However, untrusted code can set this
266 : * flag, and versions of Linux before 2.6.25 do not clear the flag
267 : * before running the signal handler, so we clear it here for safety.
268 : * See http://code.google.com/p/nativeclient/issues/detail?id=1495
269 : */
270 292091 : __asm__("cld");
271 : #endif
272 :
273 292091 : NaClSignalContextFromHandler(&sig_ctx, uc);
274 292091 : GetCurrentThread(&sig_ctx, &is_untrusted, &natp);
275 :
276 : #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
277 : /*
278 : * On Linux, the kernel does not restore %gs when entering the
279 : * signal handler, so we must do that here. We need to do this for
280 : * TLS to work and for glibc's syscall wrappers to work, because
281 : * some builds of glibc fetch a syscall function pointer from the
282 : * static TLS area. There is the potential for vulnerabilities if
283 : * we call glibc without restoring %gs (such as
284 : * http://code.google.com/p/nativeclient/issues/detail?id=1607),
285 : * although the risk is reduced because the untrusted %gs segment
286 : * has an extent of only 4 bytes (see
287 : * http://code.google.com/p/nativeclient/issues/detail?id=2176).
288 : *
289 : * Note that, in comparison, Breakpad tries to avoid using libc
290 : * calls at all when a crash occurs.
291 : *
292 : * For comparison, on Mac OS X, the kernel *does* restore the
293 : * original %gs when entering the signal handler. On Mac, our
294 : * assignment to %gs here wouldn't be necessary, but it wouldn't be
295 : * harmful either. However, this code is not currently used on Mac
296 : * OS X.
297 : *
298 : * Both Linux and Mac OS X necessarily restore %cs, %ds, and %ss
299 : * otherwise we would have a hard time handling signals generated by
300 : * untrusted code at all.
301 : *
302 : * Note that we check natp (which is based on %gs) rather than
303 : * is_untrusted (which is based on %cs) because we need to handle
304 : * the case where %gs is set to the untrusted-code value but %cs is
305 : * not.
306 : *
307 : * GCC's stack protector (-fstack-protector) will make use of %gs even before
308 : * we have a chance to restore it. It is important that this function is not
309 : * compiled with -fstack-protector.
310 : */
311 : if (natp != NULL) {
312 : NaClSetGs(natp->user.trusted_gs);
313 : }
314 : #endif
315 :
316 292091 : if (sig != SIGINT && sig != SIGQUIT) {
317 292091 : if (NaClThreadSuspensionSignalHandler(sig, &sig_ctx, is_untrusted, natp)) {
318 10099 : NaClSignalContextToHandler(uc, &sig_ctx);
319 : /* Resume untrusted code using possibly modified register state. */
320 10099 : return;
321 : }
322 : }
323 :
324 281976 : if (is_untrusted &&
325 9508 : (sig == SIGSEGV || sig == SIGILL || sig == SIGFPE ||
326 : (NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips && sig == SIGTRAP))) {
327 266383 : if (DispatchToUntrustedHandler(natp, &sig_ctx)) {
328 266374 : NaClSignalContextToHandler(uc, &sig_ctx);
329 : /* Resume untrusted code using the modified register state. */
330 266374 : return;
331 : }
332 : }
333 :
334 15602 : if (g_handler_func != NULL) {
335 15591 : g_handler_func(sig, &sig_ctx, is_untrusted);
336 15591 : return;
337 : }
338 :
339 11 : NaClSignalHandleUntrusted(sig, &sig_ctx, is_untrusted);
340 :
341 2 : FindAndRunHandler(sig, info, uc);
342 : }
343 :
344 :
345 : /*
346 : * Check that the current process has no signal handlers registered
347 : * that we won't override with safe handlers.
348 : *
349 : * We want to discourage Chrome or libraries from registering signal
350 : * handlers themselves, because those signal handlers are often not
351 : * safe when triggered from untrusted code. For background, see:
352 : * http://code.google.com/p/nativeclient/issues/detail?id=1607
353 : */
354 290 : static void AssertNoOtherSignalHandlers(void) {
355 : unsigned int index;
356 : int signum;
357 : char handled_by_nacl[NSIG];
358 :
359 : /* 0 is not a valid signal number. */
360 18850 : for (signum = 1; signum < NSIG; signum++) {
361 18560 : handled_by_nacl[signum] = 0;
362 : }
363 3480 : for (index = 0; index < NACL_ARRAY_SIZE(s_Signals); index++) {
364 3190 : signum = s_Signals[index];
365 3190 : CHECK(signum > 0);
366 3190 : CHECK(signum < NSIG);
367 3190 : handled_by_nacl[signum] = 1;
368 : }
369 18850 : for (signum = 1; signum < NSIG; signum++) {
370 : struct sigaction sa;
371 :
372 18560 : if (handled_by_nacl[signum])
373 3190 : continue;
374 :
375 15370 : if (sigaction(signum, NULL, &sa) != 0) {
376 : /*
377 : * Don't complain if the kernel does not consider signum to be a
378 : * valid signal number, which produces EINVAL.
379 : */
380 580 : if (errno != EINVAL) {
381 0 : NaClLog(LOG_FATAL, "AssertNoOtherSignalHandlers: "
382 : "sigaction() call failed for signal %d: errno=%d\n",
383 0 : signum, errno);
384 : }
385 : } else {
386 14790 : if ((sa.sa_flags & SA_SIGINFO) == 0) {
387 14790 : if (sa.sa_handler == SIG_DFL || sa.sa_handler == SIG_IGN)
388 14790 : continue;
389 : } else {
390 : /*
391 : * It is not strictly legal for sa_sigaction to contain NULL
392 : * or SIG_IGN, but Valgrind reports SIG_IGN for signal 64, so
393 : * we allow it here.
394 : */
395 0 : if (sa.sa_sigaction == NULL ||
396 0 : sa.sa_sigaction == (void (*)(int, siginfo_t *, void *)) SIG_IGN)
397 0 : continue;
398 : }
399 0 : NaClLog(LOG_FATAL, "AssertNoOtherSignalHandlers: "
400 : "A signal handler is registered for signal %d\n", signum);
401 : }
402 : }
403 290 : }
404 :
405 290 : void NaClSignalHandlerInit(void) {
406 : struct sigaction sa;
407 : unsigned int a;
408 :
409 : /*
410 : * Android adds a handler for SIGPIPE in the dynamic linker.
411 : */
412 : if (NACL_ANDROID)
413 : CHECK(signal(SIGPIPE, SIG_IGN) != SIG_ERR);
414 :
415 290 : AssertNoOtherSignalHandlers();
416 :
417 290 : memset(&sa, 0, sizeof(sa));
418 290 : sigemptyset(&sa.sa_mask);
419 290 : sa.sa_sigaction = SignalCatch;
420 290 : sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
421 :
422 : /*
423 : * Mask all signals we catch to prevent re-entry.
424 : *
425 : * In particular, NACL_THREAD_SUSPEND_SIGNAL must be masked while we
426 : * are handling a fault from untrusted code, otherwise the
427 : * suspension signal will interrupt the trusted fault handler. That
428 : * would cause NaClAppThreadGetSuspendedRegisters() to report
429 : * trusted-code register state rather than untrusted-code register
430 : * state from the point where the fault occurred.
431 : */
432 3480 : for (a = 0; a < NACL_ARRAY_SIZE(s_Signals); a++) {
433 3190 : sigaddset(&sa.sa_mask, s_Signals[a]);
434 : }
435 :
436 : /* Install all handlers */
437 3480 : for (a = 0; a < NACL_ARRAY_SIZE(s_Signals); a++) {
438 3190 : if (sigaction(s_Signals[a], &sa, &s_OldActions[a]) != 0) {
439 0 : NaClLog(LOG_FATAL, "Failed to install handler for %d.\n\tERR:%s\n",
440 0 : s_Signals[a], strerror(errno));
441 : }
442 : }
443 290 : }
444 :
445 8 : void NaClSignalHandlerFini(void) {
446 : unsigned int a;
447 :
448 : /* Remove all handlers */
449 96 : for (a = 0; a < NACL_ARRAY_SIZE(s_Signals); a++) {
450 88 : if (sigaction(s_Signals[a], &s_OldActions[a], NULL) != 0) {
451 0 : NaClLog(LOG_FATAL, "Failed to unregister handler for %d.\n\tERR:%s\n",
452 0 : s_Signals[a], strerror(errno));
453 : }
454 : }
455 8 : }
|