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