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

Side by Side Diff: src/nonsfi/linux/irt_signal_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
(Empty)
1 /*
2 * Copyright (c) 2015 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 <pthread.h>
9 #include <signal.h>
10 #include <stdint.h>
11 #include <string.h>
12 #include <unistd.h>
13
14 #include "native_client/src/include/elf_constants.h"
15 #include "native_client/src/include/nacl/nacl_exception.h"
16 #include "native_client/src/include/nacl_macros.h"
17 #include "native_client/src/nonsfi/linux/irt_signal_handling.h"
18 #include "native_client/src/nonsfi/linux/linux_sys_private.h"
19 #include "native_client/src/nonsfi/linux/linux_syscall_defines.h"
20 #include "native_client/src/nonsfi/linux/linux_syscall_structs.h"
21 #include "native_client/src/public/linux_syscalls/sys/syscall.h"
22 #include "native_client/src/public/nonsfi/irt_signal_handling.h"
23 #include "native_client/src/untrusted/irt/irt.h"
24
25 typedef struct compat_sigaltstack {
26 uint32_t ss_sp;
27 int32_t ss_flags;
28 uint32_t ss_size;
29 } linux_stack_t;
30
31
32 /* From linux/arch/arm/include/asm/ucontext.h */
33 struct linux_ucontext_t {
34 uint32_t uc_flags;
35 uint32_t uc_link;
36 linux_stack_t uc_stack;
37 linux_mcontext_t uc_mcontext;
38 linux_sigset_t uc_sigmask;
39 /* More data follows which we don't care about. */
40 };
41
42 pthread_mutex_t g_signal_handler_mutex = PTHREAD_MUTEX_INITIALIZER;
43 static NaClExceptionHandler g_signal_handler_function_pointer = NULL;
44 static int g_signal_handler_initialized = 0;
45 static int g_tgid = 0;
46 static int g_main_tid;
47
48 static void machine_context_to_register(const linux_mcontext_t *mctx,
49 NaClUserRegisterState *dest) {
50 #if defined(__i386__)
51 #define COPY_REG(A) dest->e##A = mctx->A
52 COPY_REG(ax);
53 COPY_REG(cx);
54 COPY_REG(dx);
55 COPY_REG(bx);
56 COPY_REG(bp);
57 COPY_REG(si);
58 COPY_REG(di);
59 #undef COPY_REG
60 dest->stack_ptr = mctx->sp;
61 dest->prog_ctr = mctx->ip;
62 dest->flags = mctx->flags;
63 #elif defined(__arm__)
64 #define COPY_REG(A) dest->A = mctx->arm_##A
65 COPY_REG(r0);
66 COPY_REG(r1);
67 COPY_REG(r2);
68 COPY_REG(r3);
69 COPY_REG(r4);
70 COPY_REG(r5);
71 COPY_REG(r6);
72 COPY_REG(r7);
73 COPY_REG(r8);
74 COPY_REG(r9);
75 COPY_REG(r10);
76 COPY_REG(r11);
77 COPY_REG(r12);
78 #undef COPY_REG
79 dest->stack_ptr = mctx->arm_sp;
80 dest->lr = mctx->arm_lr;
81 dest->prog_ctr = mctx->arm_pc;
82 dest->cpsr = mctx->arm_cpsr;
83 #else
84 # error Unsupported architecture
85 #endif
86 }
87
88 void exception_frame_from_signal_context(
89 struct NonSfiExceptionFrame *frame,
90 const void *raw_ctx) {
91 const struct linux_ucontext_t *uctx = (struct linux_ucontext_t *) raw_ctx;
92 const linux_mcontext_t *mctx = &uctx->uc_mcontext;
93 frame->context.size = (((uintptr_t) (&frame->portable + 1))
94 - (uintptr_t) &frame->context);
95 frame->context.portable_context_offset = ((uintptr_t) &frame->portable
96 - (uintptr_t) &frame->context);
97 frame->context.portable_context_size = sizeof(frame->portable);
98 frame->context.regs_size = sizeof(frame->context.regs);
99
100 memset(frame->context.reserved, 0, sizeof(frame->context.reserved));
101 machine_context_to_register(mctx, &frame->context.regs);
102 frame->portable.prog_ctr = frame->context.regs.prog_ctr;
103 frame->portable.stack_ptr = frame->context.regs.stack_ptr;
104
105 #if defined(__i386__)
106 frame->context.arch = EM_386;
107 frame->portable.frame_ptr = frame->context.regs.ebp;
108 #elif defined(__arm__)
109 frame->context.arch = EM_ARM;
110 /* R11 is frame pointer in ARM mode, R8 is frame pointer in thumb mode. */
111 frame->portable.frame_ptr = frame->context.regs.r11;
112 #else
113 # error Unsupported architecture
114 #endif
115 }
116
117 /* A replacement of sigreturn. It does not restore the signal mask. */
118 static void __attribute__((noreturn))
119 _nonsfi_restore_context(const linux_mcontext_t *mctx) {
Junichi Uekawa 2015/07/01 02:14:57 this is not python code, don't prepend function na
Luis Héctor Chávez 2015/07/06 23:44:59 Done.
120
121 #if defined(__i386__)
122
123 #define OFFSET(name) \
124 [name] "i" (offsetof(linux_mcontext_t, name))
125 #define RESTORE_SEGMENT(name) \
126 "mov %c[" #name "](%%eax), %%" #name "\n"
127 #define RESTORE(name) \
128 "movl %c[" #name "](%%eax), %%e" #name "\n"
129
130 __asm__ __volatile__(
131 "mov %0, %%eax\n"
132
133 /* Restore floating-point environment */
134 "mov %c[fpstate](%%eax), %%ecx\n"
135 "fldenv (%%ecx)\n"
136
137 /* Restore all segment registers */
138 RESTORE_SEGMENT(gs)
139 RESTORE_SEGMENT(fs)
140 RESTORE_SEGMENT(es)
141 RESTORE_SEGMENT(ds)
142
143 /*
144 * Restore the rest of the registers except for dx, cx (scratch) and ax.
145 */
146 RESTORE(di)
147 RESTORE(si)
148 RESTORE(bp)
149 RESTORE(bx)
150
151 /*
152 * Prepare the last registers. eip, eflags, eax, and ecx should be on the
153 * top of the new stack. Once that is done and esp restored, we can
154 * safely restore them.
155 */
156 "mov %c[sp](%%eax), %%ecx\n"
157 "mov %c[ip](%%eax), %%edx\n"
158 "mov %%edx, -4(%%ecx)\n"
159 "mov %c[flags](%%eax), %%edx\n"
160 "mov %%edx, -8(%%ecx)\n"
161 "mov %c[ax](%%eax), %%edx\n"
162 "mov %%edx, -12(%%ecx)\n"
163 "mov %c[cx](%%eax), %%edx\n"
164 "mov %%edx, -16(%%ecx)\n"
165 RESTORE(dx)
166 "sub $16, %%ecx\n"
167 "mov %%ecx, %%esp\n"
168
169 /*
170 * Finally pop the last registers off the stack and return to
171 * simultaneously restore esp and eip.
172 */
173 "pop %%ecx\n"
174 "pop %%eax\n"
175 "popfd\n"
176 "ret\n"
177 :
178 : "X" (mctx),
179 OFFSET(gs),
180 OFFSET(fs),
181 OFFSET(es),
182 OFFSET(ds),
183 OFFSET(di),
184 OFFSET(si),
185 OFFSET(bp),
186 OFFSET(sp),
187 OFFSET(bx),
188 OFFSET(dx),
189 OFFSET(cx),
190 OFFSET(ax),
191 OFFSET(ip),
192 OFFSET(flags),
193 OFFSET(fpstate)
194 );
195
196 #undef OFFSET
197 #undef RESTORE
198 #undef RESTORE_SEGMENT
199
200 #elif defined(__arm__)
201
202 /* TODO(lhchavez): Implement this. */
Junichi Uekawa 2015/07/01 02:14:57 erm... is this required ?
Luis Héctor Chávez 2015/07/06 23:44:59 It is. I wanted to have feedback on the rest of th
203
204 #else
205 # error Unsupported architecture
206 #endif
207
208 /* Should never reach this. */
209 abort();
210 }
211
212 static __attribute__((noreturn))
213 void restore_context(void *raw_ctx) {
214 const struct linux_ucontext_t *uctx = (struct linux_ucontext_t *) raw_ctx;
215 const linux_mcontext_t *mctx = &uctx->uc_mcontext;
216 _nonsfi_restore_context(mctx);
217 }
218
219 static void signal_catch(int sig, linux_siginfo_t *info, void *uc) {
220 if (g_signal_handler_function_pointer) {
221 struct NonSfiExceptionFrame exception_frame;
222 exception_frame_from_signal_context(&exception_frame, uc);
223 g_signal_handler_function_pointer(&exception_frame.context);
224 }
225 restore_context(uc);
226 }
227
228 static void nonsfi_install_signal_handler_locked() {
229 struct linux_sigaction sa;
230
231 memset(&sa, 0, sizeof(sa));
232 sa.sa_sigaction = signal_catch;
233
234 /*
235 * User signal handler can be recursively interrupted to avoid having
236 * to allow sigreturn/sigprocmask.
237 */
238 sa.sa_flags = LINUX_SA_SIGINFO | LINUX_SA_NODEFER;
239 sigset_t *mask = (sigset_t*)&sa.sa_mask;
240 sigemptyset(mask);
241
242 /*
243 * Install a single handler. Multiple signals can be multiplexed in
244 * userspace.
245 */
246 if (linux_sigaction(LINUX_SIGUSR1, &sa, NULL) != 0)
247 abort();
248 }
249
250 void nonsfi_initialize_signal_handler_locked() {
251 if (g_signal_handler_initialized)
252 return;
253 nonsfi_install_exception_handler_locked();
254 nonsfi_install_signal_handler_locked();
255 g_tgid = getpid();
256 g_main_tid = syscall(__NR_gettid);
257 g_signal_handler_initialized = 1;
258 }
259
260 /*
261 * Initialize signal handlers before entering sandbox.
262 */
263 void nonsfi_initialize_signal_handler() {
264 if (pthread_mutex_lock(&g_signal_handler_mutex) != 0)
265 abort();
266 nonsfi_initialize_signal_handler_locked();
267 if (pthread_mutex_unlock(&g_signal_handler_mutex) != 0)
268 abort();
269 }
270
271 int nacl_signal_set_handler(NaClIrtSignalHandler handler) {
272 if (pthread_mutex_lock(&g_signal_handler_mutex) != 0)
273 abort();
274 nonsfi_initialize_signal_handler_locked();
275 g_signal_handler_function_pointer = handler;
276 if (pthread_mutex_unlock(&g_signal_handler_mutex) != 0)
277 abort();
278 return 0;
279 }
280
281 int nacl_signal_send_async_signal(nacl_irt_tid_t tid) {
282 if (!g_signal_handler_initialized)
283 return ESRCH;
284 if (tid == 0)
285 tid = g_main_tid;
286 if (linux_tgkill(g_tgid, tid, LINUX_SIGUSR1) == -1)
287 return errno;
288 return 0;
289 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698