Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1142)

Side by Side Diff: src/nonsfi/linux/irt_exception_handling.c

Issue 1212613002: Non-SFI mode: Add Linux asynchronous signal support (Closed) Base URL: https://chromium.googlesource.com/native_client/src/native_client.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2014 The Native Client Authors. All rights reserved. 2 * Copyright (c) 2014 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be 3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file. 4 * found in the LICENSE file.
5 */ 5 */
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <pthread.h> 8 #include <pthread.h>
9 #include <signal.h> 9 #include <signal.h>
10 #include <stdint.h> 10 #include <stdint.h>
11 #include <string.h> 11 #include <string.h>
12 #include <unistd.h> 12 #include <unistd.h>
13 13
14 #include "native_client/src/include/elf_constants.h" 14 #include "native_client/src/include/elf_constants.h"
15 #include "native_client/src/include/nacl/nacl_exception.h" 15 #include "native_client/src/include/nacl/nacl_exception.h"
16 #include "native_client/src/include/nacl_macros.h" 16 #include "native_client/src/include/nacl_macros.h"
17 #include "native_client/src/nonsfi/linux/irt_signal_handling.h"
17 #include "native_client/src/nonsfi/linux/linux_sys_private.h" 18 #include "native_client/src/nonsfi/linux/linux_sys_private.h"
18 #include "native_client/src/nonsfi/linux/linux_syscall_defines.h" 19 #include "native_client/src/nonsfi/linux/linux_syscall_defines.h"
19 #include "native_client/src/nonsfi/linux/linux_syscall_structs.h" 20 #include "native_client/src/nonsfi/linux/linux_syscall_structs.h"
20 #include "native_client/src/public/nonsfi/irt_exception_handling.h"
21 #include "native_client/src/untrusted/irt/irt.h" 21 #include "native_client/src/untrusted/irt/irt.h"
22 22
23 typedef struct compat_sigaltstack {
Mark Seaborn 2015/06/26 18:31:59 If you're moving large chunks of code around, woul
Luis Héctor Chávez 2015/07/06 23:44:59 Done.
Mark Seaborn 2015/07/16 23:21:16 Hmm, I don't see a summary in the commit message..
Luis Héctor Chávez 2015/07/20 18:13:46 I did not realize that `git cl upload` does not re
24 uint32_t ss_sp;
25 int32_t ss_flags;
26 uint32_t ss_size;
27 } linux_stack_t;
28
29 #if defined(__i386__)
30
31 /* From linux/arch/x86/include/uapi/asm/sigcontext32.h */
32 struct sigcontext_ia32 {
33 unsigned short gs, __gsh;
34 unsigned short fs, __fsh;
35 unsigned short es, __esh;
36 unsigned short ds, __dsh;
37 unsigned int di;
38 unsigned int si;
39 unsigned int bp;
40 unsigned int sp;
41 unsigned int bx;
42 unsigned int dx;
43 unsigned int cx;
44 unsigned int ax;
45 unsigned int trapno;
46 unsigned int err;
47 unsigned int ip;
48 unsigned short cs, __csh;
49 unsigned int flags;
50 unsigned int sp_at_signal;
51 unsigned short ss, __ssh;
52 unsigned int fpstate;
53 unsigned int oldmask;
54 unsigned int cr2;
55 };
56
57 typedef struct sigcontext_ia32 linux_mcontext_t;
58
59 #elif defined(__arm__)
60
61 /* From linux/arch/arm/include/uapi/asm/sigcontext.h */
62 struct sigcontext_arm {
63 uint32_t trap_no;
64 uint32_t error_code;
65 uint32_t oldmask;
66 uint32_t arm_r0;
67 uint32_t arm_r1;
68 uint32_t arm_r2;
69 uint32_t arm_r3;
70 uint32_t arm_r4;
71 uint32_t arm_r5;
72 uint32_t arm_r6;
73 uint32_t arm_r7;
74 uint32_t arm_r8;
75 uint32_t arm_r9;
76 uint32_t arm_r10;
77 uint32_t arm_r11; /* fp */
78 uint32_t arm_r12; /* ip */
79 uint32_t arm_sp;
80 uint32_t arm_lr;
81 uint32_t arm_pc;
82 uint32_t arm_cpsr;
83 uint32_t fault_address;
84 };
85
86 typedef struct sigcontext_arm linux_mcontext_t;
87
88 #else
89 #error "unsupported architecture"
90 #endif
91
92 /* From linux/arch/arm/include/asm/ucontext.h */
93 struct linux_ucontext_t {
94 uint32_t uc_flags;
95 uint32_t uc_link;
96 linux_stack_t uc_stack;
97 linux_mcontext_t uc_mcontext;
98 linux_sigset_t uc_sigmask;
99 /* More data follows which we don't care about. */
100 };
101
102 /* 23 /*
103 * Crash signals to handle. The differences from SFI NaCl are that 24 * Crash signals to handle. The differences from SFI NaCl are that
104 * NonSFI NaCl does not use NACL_THREAD_SUSPEND_SIGNAL (==SIGUSR1), 25 * NonSFI NaCl does not use NACL_THREAD_SUSPEND_SIGNAL (==SIGUSR1),
105 */ 26 */
106 static const int kSignals[] = { 27 static const int kSignals[] = {
107 LINUX_SIGSTKFLT, 28 LINUX_SIGSTKFLT,
108 LINUX_SIGINT, LINUX_SIGQUIT, LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGBUS, 29 LINUX_SIGINT, LINUX_SIGQUIT, LINUX_SIGILL, LINUX_SIGTRAP, LINUX_SIGBUS,
109 LINUX_SIGFPE, LINUX_SIGSEGV, 30 LINUX_SIGFPE, LINUX_SIGSEGV,
110 /* Handle SIGABRT in case someone sends it asynchronously using kill(). */ 31 /* Handle SIGABRT in case someone sends it asynchronously using kill(). */
111 LINUX_SIGABRT, 32 LINUX_SIGABRT,
112 }; 33 };
113 34
114 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; 35 extern pthread_mutex_t g_signal_handler_mutex;
115 static NaClExceptionHandler g_signal_handler_function_pointer = NULL; 36 static NaClExceptionHandler g_exception_handler_function_pointer = NULL;
116 static int g_signal_handler_initialized = 0;
117 37
118 struct NonSfiExceptionFrame { 38 /* Signal handlers, responsible for calling the registered handlers. */
119 struct NaClExceptionContext context; 39 static void exception_catch(int sig, linux_siginfo_t *info, void *uc) {
120 struct NaClExceptionPortableContext portable; 40 if (g_exception_handler_function_pointer) {
121 };
122
123 static void machine_context_to_register(const linux_mcontext_t *mctx,
124 NaClUserRegisterState *dest) {
125 #if defined(__i386__)
126 #define COPY_REG(A) dest->e##A = mctx->A
127 COPY_REG(ax);
128 COPY_REG(cx);
129 COPY_REG(dx);
130 COPY_REG(bx);
131 COPY_REG(bp);
132 COPY_REG(si);
133 COPY_REG(di);
134 #undef COPY_REG
135 dest->stack_ptr = mctx->sp;
136 dest->prog_ctr = mctx->ip;
137 dest->flags = mctx->flags;
138 #elif defined(__arm__)
139 #define COPY_REG(A) dest->A = mctx->arm_##A
140 COPY_REG(r0);
141 COPY_REG(r1);
142 COPY_REG(r2);
143 COPY_REG(r3);
144 COPY_REG(r4);
145 COPY_REG(r5);
146 COPY_REG(r6);
147 COPY_REG(r7);
148 COPY_REG(r8);
149 COPY_REG(r9);
150 COPY_REG(r10);
151 COPY_REG(r11);
152 COPY_REG(r12);
153 #undef COPY_REG
154 dest->stack_ptr = mctx->arm_sp;
155 dest->lr = mctx->arm_lr;
156 dest->prog_ctr = mctx->arm_pc;
157 dest->cpsr = mctx->arm_cpsr;
158 #else
159 # error Unsupported architecture
160 #endif
161 }
162
163 static void exception_frame_from_signal_context(
164 struct NonSfiExceptionFrame *frame,
165 const void *raw_ctx) {
166 const struct linux_ucontext_t *uctx = (struct linux_ucontext_t *) raw_ctx;
167 const linux_mcontext_t *mctx = &uctx->uc_mcontext;
168 frame->context.size = (((uintptr_t) (&frame->portable + 1))
169 - (uintptr_t) &frame->context);
170 frame->context.portable_context_offset = ((uintptr_t) &frame->portable
171 - (uintptr_t) &frame->context);
172 frame->context.portable_context_size = sizeof(frame->portable);
173 frame->context.regs_size = sizeof(frame->context.regs);
174
175 memset(frame->context.reserved, 0, sizeof(frame->context.reserved));
176 machine_context_to_register(mctx, &frame->context.regs);
177 frame->portable.prog_ctr = frame->context.regs.prog_ctr;
178 frame->portable.stack_ptr = frame->context.regs.stack_ptr;
179
180 #if defined(__i386__)
181 frame->context.arch = EM_386;
182 frame->portable.frame_ptr = frame->context.regs.ebp;
183 #elif defined(__arm__)
184 frame->context.arch = EM_ARM;
185 /* R11 is frame pointer in ARM mode, R8 is frame pointer in thumb mode. */
186 frame->portable.frame_ptr = frame->context.regs.r11;
187 #else
188 # error Unsupported architecture
189 #endif
190 }
191
192 /* Signal handler, responsible for calling the registered handler. */
193 static void signal_catch(int sig, linux_siginfo_t *info, void *uc) {
194 if (g_signal_handler_function_pointer) {
195 struct NonSfiExceptionFrame exception_frame; 41 struct NonSfiExceptionFrame exception_frame;
196 exception_frame_from_signal_context(&exception_frame, uc); 42 exception_frame_from_signal_context(&exception_frame, uc);
197 g_signal_handler_function_pointer(&exception_frame.context); 43 g_exception_handler_function_pointer(&exception_frame.context);
198 } 44 }
199 _exit(-sig); 45 _exit(-sig);
200 } 46 }
201 47
202 static void nonsfi_initialize_signal_handler_locked() { 48 void nonsfi_install_exception_handler_locked() {
203 struct linux_sigaction sa; 49 struct linux_sigaction sa;
204 unsigned int a; 50 unsigned int a;
205 51
206 memset(&sa, 0, sizeof(sa)); 52 memset(&sa, 0, sizeof(sa));
207 sa.sa_sigaction = signal_catch; 53 sa.sa_sigaction = exception_catch;
208 sa.sa_flags = LINUX_SA_SIGINFO | LINUX_SA_ONSTACK; 54 sa.sa_flags = LINUX_SA_SIGINFO | LINUX_SA_ONSTACK;
209 55
210 /* 56 /*
211 * Reuse the sigemptyset/sigaddset for the first 32 bits of the 57 * Reuse the sigemptyset/sigaddset for the first 32 bits of the
212 * sigmask. Works on little endian systems only. 58 * sigmask. Works on little endian systems only.
213 */ 59 */
214 sigset_t *mask = (sigset_t*)&sa.sa_mask; 60 sigset_t *mask = (sigset_t*)&sa.sa_mask;
215 sigemptyset(mask); 61 sigemptyset(mask);
216 62
217 /* Mask all signals we catch to prevent re-entry. */ 63 /* Mask all signals we catch to prevent re-entry. */
218 for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) { 64 for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) {
219 sigaddset(mask, kSignals[a]); 65 sigaddset(mask, kSignals[a]);
220 } 66 }
221 67
222 /* Install all handlers. */ 68 /* Install all handlers. */
223 for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) { 69 for (a = 0; a < NACL_ARRAY_SIZE(kSignals); a++) {
224 if (linux_sigaction(kSignals[a], &sa, NULL) != 0) 70 if (linux_sigaction(kSignals[a], &sa, NULL) != 0)
225 abort(); 71 abort();
226 } 72 }
227 } 73 }
228 74
229 /*
230 * Initialize signal handlers before entering sandbox.
231 */
232 void nonsfi_initialize_signal_handler() {
233 if (pthread_mutex_lock(&g_mutex) != 0)
234 abort();
235 if (!g_signal_handler_initialized) {
236 nonsfi_initialize_signal_handler_locked();
237 g_signal_handler_initialized = 1;
238 }
239 if (pthread_mutex_unlock(&g_mutex) != 0)
240 abort();
241 }
242
243 int nacl_exception_get_and_set_handler(NaClExceptionHandler handler, 75 int nacl_exception_get_and_set_handler(NaClExceptionHandler handler,
244 NaClExceptionHandler *old_handler) { 76 NaClExceptionHandler *old_handler) {
245 nonsfi_initialize_signal_handler(); 77 if (pthread_mutex_lock(&g_signal_handler_mutex) != 0)
246 if (pthread_mutex_lock(&g_mutex) != 0)
247 abort(); 78 abort();
79 nonsfi_initialize_signal_handler_locked();
248 if (old_handler) 80 if (old_handler)
249 *old_handler = g_signal_handler_function_pointer; 81 *old_handler = g_exception_handler_function_pointer;
250 g_signal_handler_function_pointer = handler; 82 g_exception_handler_function_pointer = handler;
251 if (pthread_mutex_unlock(&g_mutex) != 0) 83 if (pthread_mutex_unlock(&g_signal_handler_mutex) != 0)
252 abort(); 84 abort();
253 return 0; 85 return 0;
254 } 86 }
255 87
256 int nacl_exception_set_handler(NaClExceptionHandler handler) { 88 int nacl_exception_set_handler(NaClExceptionHandler handler) {
257 return nacl_exception_get_and_set_handler(handler, NULL); 89 return nacl_exception_get_and_set_handler(handler, NULL);
258 } 90 }
259 91
260 int nacl_exception_clear_flag(void) { 92 int nacl_exception_clear_flag(void) {
261 /* 93 /*
(...skipping 24 matching lines...) Expand all
286 if (linux_sigprocmask(LINUX_SIG_UNBLOCK, &mask, NULL) != 0) 118 if (linux_sigprocmask(LINUX_SIG_UNBLOCK, &mask, NULL) != 0)
287 abort(); 119 abort();
288 120
289 return 0; 121 return 0;
290 } 122 }
291 123
292 int nacl_exception_set_stack(void *p, size_t s) { 124 int nacl_exception_set_stack(void *p, size_t s) {
293 /* Not implemented yet. */ 125 /* Not implemented yet. */
294 return ENOSYS; 126 return ENOSYS;
295 } 127 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698