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 #ifndef NATIVE_CLIENT_SERVICE_RUNTIME_NACL_SIGNAL_H__ 8 #define NATIVE_CLIENT_SERVICE_RUNTIME_NACL_SIGNAL_H__ 1 9 10 /* 11 * The nacl_signal module provides a platform independent mechanism for 12 * trapping signals encountered while running a Native Client executable. 13 * Signal handlers can be installed which will receive a POSIX signal number 14 * and a platform dependent signal object. Accessors are provided to convert 15 * to and from architecture dependent CPU state structures. 16 */ 17 18 #include "native_client/src/include/build_config.h" 19 #include "native_client/src/include/nacl_base.h" 20 #include "native_client/src/include/nacl/nacl_exception.h" 21 22 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 23 #if NACL_BUILD_SUBARCH == 32 24 #include "native_client/src/trusted/service_runtime/arch/x86_32/nacl_signal_32.h" 25 #elif NACL_BUILD_SUBARCH == 64 26 #include "native_client/src/trusted/service_runtime/arch/x86_64/nacl_signal_64.h" 27 #else 28 #error "Woe to the service runtime. Is it running on a 128-bit machine?!?" 29 #endif 30 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_arm 31 #include "native_client/src/trusted/service_runtime/arch/arm/nacl_signal_arm.h" 32 #elif NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips 33 #include "native_client/src/trusted/service_runtime/arch/mips/nacl_signal_mips.h" 34 #else 35 #error Unknown platform! 36 #endif 37 38 39 EXTERN_C_BEGIN 40 41 struct NaClApp; 42 struct NaClAppThread; 43 struct NaClExceptionFrame; 44 45 /* 46 * TODO(halyavin): These signal numbers are part of an external ABI 47 * exposed through NaCl's GDB debug stub. We need to find a directory 48 * to place such headers. 49 */ 50 #define NACL_ABI_SIGILL 4 51 #define NACL_ABI_SIGTRAP 5 52 #define NACL_ABI_SIGKILL 9 53 #define NACL_ABI_SIGSEGV 11 54 55 #define NACL_ABI_WEXITSTATUS(status) (((status) & 0xff00) >> 8) 56 #define NACL_ABI_WTERMSIG(status) ((status) & 0x7f) 57 #define NACL_ABI_WIFEXITED(status) (NACL_ABI_WTERMSIG(status) == 0) 58 #define NACL_ABI_WIFSIGNALED(status) ((((status) + 1) & 0x7f) > 1) 59 #define NACL_ABI_W_EXITCODE(ret, sig) ((((ret) & 0xff) << 8) + ((sig) & 0x7f)) 60 61 #if NACL_WINDOWS 62 enum PosixSignals { 63 SIGINT = 2, 64 SIGQUIT = 3, 65 SIGILL = 4, 66 SIGTRACE= 5, 67 SIGABRT = 6, 68 SIGBUS = 7, 69 SIGFPE = 8, 70 SIGKILL = 9, 71 SIGSEGV = 11, 72 SIGSTKFLT = 16, 73 }; 74 #endif 75 76 #if NACL_LINUX 77 # define NACL_THREAD_SUSPEND_SIGNAL SIGUSR1 78 #endif 79 80 81 /* 82 * Prototype for a signal handler. The handler will receive the POSIX 83 * signal number and an opaque platform dependent signal object. 84 */ 85 typedef void (*NaClSignalHandler)(int sig_num, 86 const struct NaClSignalContext *regs, 87 int is_untrusted); 88 89 90 /* 91 * This allows setting a larger signal stack size than the default. 92 * This is for use by tests which may want to call functions such as 93 * fprintf() to print debugging info in the event of a failure, 94 * because fprintf() requires a larger stack. 95 */ 96 void NaClSignalStackSetSize(uint32_t size); 97 98 /* 99 * Allocates a stack suitable for passing to 100 * NaClSignalStackRegister(), for use as a stack for signal handlers. 101 * This can be called in any thread. 102 * Stores the result in *result; returns 1 on success, 0 on failure. 103 */ 104 int NaClSignalStackAllocate(void **result); 105 106 /* 107 * Deallocates a stack allocated by NaClSignalStackAllocate(). 108 * This can be called in any thread. 109 */ 110 void NaClSignalStackFree(void *stack); 111 112 /* 113 * Registers a signal stack for use in the current thread. 114 */ 115 void NaClSignalStackRegister(void *stack); 116 117 /* 118 * Undoes the effect of NaClSignalStackRegister(). 119 */ 120 void NaClSignalStackUnregister(void); 121 122 void NaClSignalTestCrashOnStartup(void); 123 124 /* 125 * Register process-wide signal handlers. 126 */ 127 void NaClSignalHandlerInit(void); 128 129 /* 130 * Undoes the effect of NaClSignalHandlerInit(). 131 */ 132 void NaClSignalHandlerFini(void); 133 134 /* 135 * Provides a signal safe method to write to stderr. 136 */ 137 ssize_t NaClSignalErrorMessage(const char *str); 138 139 /* 140 * Replace the signal handler that is run after NaCl restores %gs on 141 * x86-32. This is only used by test code. 142 */ 143 void NaClSignalHandlerSet(NaClSignalHandler func); 144 145 /* 146 * Fill a signal context structure from the raw platform dependent 147 * signal information. 148 */ 149 void NaClSignalContextFromHandler(struct NaClSignalContext *sig_ctx, 150 const void *raw_ctx); 151 152 /* 153 * Update the raw platform dependent signal information from the 154 * signal context structure. 155 */ 156 void NaClSignalContextToHandler(void *raw_ctx, 157 const struct NaClSignalContext *sig_ctx); 158 159 160 int NaClSignalContextIsUntrusted(struct NaClAppThread *natp, 161 const struct NaClSignalContext *sig_ctx); 162 163 int NaClSignalCheckSandboxInvariants(const struct NaClSignalContext *regs, 164 struct NaClAppThread *natp); 165 166 /* 167 * A basic handler which will exit with -signal_number when 168 * a signal is encountered in the untrusted code, otherwise 169 * the signal is passed to the next handler. 170 */ 171 void NaClSignalHandleUntrusted(int signal_number, 172 const struct NaClSignalContext *regs, 173 int is_untrusted); 174 175 176 void NaClSignalSetUpExceptionFrame(volatile struct NaClExceptionFrame *frame, 177 const struct NaClSignalContext *regs, 178 uint32_t context_user_addr); 179 180 #if NACL_OSX 181 182 # include <mach/thread_status.h> 183 184 void NaClSignalContextFromMacThreadState(struct NaClSignalContext *dest, 185 const x86_thread_state_t *src); 186 void NaClSignalContextToMacThreadState(x86_thread_state_t *dest, 187 const struct NaClSignalContext *src); 188 189 #endif 190 191 192 EXTERN_C_END 193 194 #endif /* NATIVE_CLIENT_SERVICE_RUNTIME_NACL_SIGNAL_H__ */ 195