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.
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"
30 * This module is based on the Posix signal model. See:
31 * http://www.opengroup.org/onlinepubs/009695399/functions/sigaction.html
35 * The signals listed here should either be handled by NaCl (or otherwise
38 static int s_Signals[] = {
39 #if NACL_ARCH(NACL_BUILD_ARCH) != NACL_mips
40 /* This signal does not exist on MIPS. */
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(). */
50 static struct sigaction s_OldActions[NACL_ARRAY_SIZE_UNSAFE(s_Signals)];
52 static NaClSignalHandler g_handler_func;
54 void NaClSignalHandlerSet(NaClSignalHandler func) {
55 g_handler_func = func;
59 * Returns, via is_untrusted, whether the signal happened while
60 * executing untrusted code.
62 * Returns, via result_thread, the NaClAppThread that untrusted code
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).
69 static void GetCurrentThread(const struct NaClSignalContext *sig_ctx,
71 struct NaClAppThread **result_thread) {
72 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
74 * For x86-32, if %cs does not match, it is untrusted code.
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.
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 struct NaClAppThread *natp = NaClTlsGetCurrentThread();
89 *result_thread = NULL;
92 * Get the address of an arbitrary local, stack-allocated variable,
93 * just for the purpose of doing a sanity check.
95 void *pointer_into_stack = &natp;
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.
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
106 DCHECK(!NaClIsUserAddr(natp->nap, (uintptr_t) pointer_into_stack));
107 *is_untrusted = NaClIsUserAddr(natp->nap, sig_ctx->prog_ctr);
108 *result_thread = natp;
111 # error Unsupported architecture
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
122 ((*result_thread)->suspend_state & NACL_APP_THREAD_UNTRUSTED) == 0) {
127 static void FindAndRunHandler(int sig, siginfo_t *info, void *uc) {
130 /* If we need to keep searching, try the old signal handler. */
131 for (a = 0; a < NACL_ARRAY_SIZE(s_Signals); a++) {
132 /* If we handle this signal */
133 if (s_Signals[a] == sig) {
134 /* If this is a real sigaction pointer... */
135 if ((s_OldActions[a].sa_flags & SA_SIGINFO) != 0) {
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
144 if (s_OldActions[a].sa_sigaction != NULL) {
145 /* then call the old handler. */
146 s_OldActions[a].sa_sigaction(sig, info, uc);
150 /* otherwise check if it is a real signal pointer */
151 if ((s_OldActions[a].sa_handler != SIG_DFL) &&
152 (s_OldActions[a].sa_handler != SIG_IGN)) {
153 /* and call the old signal. */
154 s_OldActions[a].sa_handler(sig);
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.
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
175 static int DispatchToUntrustedHandler(struct NaClAppThread *natp,
176 struct NaClSignalContext *regs) {
177 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;
183 if (!NaClSignalCheckSandboxInvariants(regs, natp)) {
186 if (nap->exception_handler == 0) {
189 if (natp->exception_flag) {
193 natp->exception_flag = 1;
195 if (natp->exception_stack == 0) {
196 new_stack_ptr = regs->stack_ptr - NACL_STACK_RED_ZONE;
198 new_stack_ptr = natp->exception_stack;
200 /* Allocate space for the stack frame, and ensure its alignment. */
202 sizeof(struct NaClExceptionFrame) - NACL_STACK_PAD_BELOW_ALIGN;
203 new_stack_ptr = new_stack_ptr & ~NACL_STACK_ALIGN_MASK;
204 new_stack_ptr -= NACL_STACK_ARGS_SIZE;
205 new_stack_ptr -= NACL_STACK_PAD_BELOW_ALIGN;
206 frame_addr = NaClUserToSysAddrRange(nap, new_stack_ptr,
207 sizeof(struct NaClExceptionFrame));
208 if (frame_addr == kNaClBadAddress) {
209 /* We cannot write the stack frame. */
212 context_user_addr = new_stack_ptr + offsetof(struct NaClExceptionFrame,
215 frame = (struct NaClExceptionFrame *) frame_addr;
216 NaClSignalSetUpExceptionFrame(frame, regs, context_user_addr);
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 regs->rdi = context_user_addr; /* Argument 1 */
223 regs->prog_ctr = NaClUserToSys(nap, nap->exception_handler);
224 regs->stack_ptr = NaClUserToSys(nap, new_stack_ptr);
225 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm
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.
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);
241 * Per Linux/MIPS convention, PIC functions assume that t9 holds
242 * the function's address on entry.
244 regs->t9 = regs->prog_ctr;
246 # error Unsupported architecture
249 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
250 regs->flags &= ~NACL_X86_DIRECTION_FLAG;
256 static void SignalCatch(int sig, siginfo_t *info, void *uc) {
257 struct NaClSignalContext sig_ctx;
259 struct NaClAppThread *natp;
261 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86
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
273 NaClSignalContextFromHandler(&sig_ctx, uc);
274 GetCurrentThread(&sig_ctx, &is_untrusted, &natp);
276 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 32
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).
289 * Note that, in comparison, Breakpad tries to avoid using libc
290 * calls at all when a crash occurs.
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
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.
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
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.
312 NaClSetGs(natp->user.trusted_gs);
316 if (sig != SIGINT && sig != SIGQUIT) {
317 if (NaClThreadSuspensionSignalHandler(sig, &sig_ctx, is_untrusted, natp)) {
318 NaClSignalContextToHandler(uc, &sig_ctx);
319 /* Resume untrusted code using possibly modified register state. */
325 (sig == SIGSEGV || sig == SIGILL || sig == SIGFPE ||
326 (NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips && sig == SIGTRAP))) {
327 if (DispatchToUntrustedHandler(natp, &sig_ctx)) {
328 NaClSignalContextToHandler(uc, &sig_ctx);
329 /* Resume untrusted code using the modified register state. */
334 if (g_handler_func != NULL) {
335 g_handler_func(sig, &sig_ctx, is_untrusted);
339 NaClSignalHandleUntrusted(sig, &sig_ctx, is_untrusted);
341 FindAndRunHandler(sig, info, uc);
346 * Check that the current process has no signal handlers registered
347 * that we won't override with safe handlers.
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
354 static void AssertNoOtherSignalHandlers(void) {
357 char handled_by_nacl[NSIG];
359 /* 0 is not a valid signal number. */
360 for (signum = 1; signum < NSIG; signum++) {
361 handled_by_nacl[signum] = 0;
363 for (index = 0; index < NACL_ARRAY_SIZE(s_Signals); index++) {
364 signum = s_Signals[index];
366 CHECK(signum < NSIG);
367 handled_by_nacl[signum] = 1;
369 for (signum = 1; signum < NSIG; signum++) {
372 if (handled_by_nacl[signum])
375 if (sigaction(signum, NULL, &sa) != 0) {
377 * Don't complain if the kernel does not consider signum to be a
378 * valid signal number, which produces EINVAL.
380 if (errno != EINVAL) {
381 NaClLog(LOG_FATAL, "AssertNoOtherSignalHandlers: "
382 "sigaction() call failed for signal %d: errno=%d\n",
386 if ((sa.sa_flags & SA_SIGINFO) == 0) {
387 if (sa.sa_handler == SIG_DFL || sa.sa_handler == SIG_IGN)
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
395 if (sa.sa_sigaction == NULL ||
396 sa.sa_sigaction == (void (*)(int, siginfo_t *, void *)) SIG_IGN)
399 NaClLog(LOG_FATAL, "AssertNoOtherSignalHandlers: "
400 "A signal handler is registered for signal %d\n", signum);
405 void NaClSignalHandlerInit(void) {
410 * Android adds a handler for SIGPIPE in the dynamic linker.
413 CHECK(signal(SIGPIPE, SIG_IGN) != SIG_ERR);
415 AssertNoOtherSignalHandlers();
417 memset(&sa, 0, sizeof(sa));
418 sigemptyset(&sa.sa_mask);
419 sa.sa_sigaction = SignalCatch;
420 sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
423 * Mask all signals we catch to prevent re-entry.
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.
432 for (a = 0; a < NACL_ARRAY_SIZE(s_Signals); a++) {
433 sigaddset(&sa.sa_mask, s_Signals[a]);
436 /* Install all handlers */
437 for (a = 0; a < NACL_ARRAY_SIZE(s_Signals); a++) {
438 if (sigaction(s_Signals[a], &sa, &s_OldActions[a]) != 0) {
439 NaClLog(LOG_FATAL, "Failed to install handler for %d.\n\tERR:%s\n",
440 s_Signals[a], strerror(errno));
445 void NaClSignalHandlerFini(void) {
448 /* Remove all handlers */
449 for (a = 0; a < NACL_ARRAY_SIZE(s_Signals); a++) {
450 if (sigaction(s_Signals[a], &s_OldActions[a], NULL) != 0) {
451 NaClLog(LOG_FATAL, "Failed to unregister handler for %d.\n\tERR:%s\n",
452 s_Signals[a], strerror(errno));