OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "library.h" | 5 #include "library.h" |
6 #include "sandbox_impl.h" | 6 #include "sandbox_impl.h" |
7 #include "syscall_table.h" | 7 #include "syscall_table.h" |
8 | 8 |
9 namespace playground { | 9 namespace playground { |
10 | 10 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 void Sandbox::setupSignalHandlers() { | 114 void Sandbox::setupSignalHandlers() { |
115 // Set SIGCHLD to SIG_DFL so that waitpid() can work | 115 // Set SIGCHLD to SIG_DFL so that waitpid() can work |
116 SysCalls sys; | 116 SysCalls sys; |
117 struct SysCalls::kernel_sigaction sa; | 117 struct SysCalls::kernel_sigaction sa; |
118 memset(&sa, 0, sizeof(sa)); | 118 memset(&sa, 0, sizeof(sa)); |
119 sa.sa_handler_ = SIG_DFL; | 119 sa.sa_handler_ = SIG_DFL; |
120 sys.sigaction(SIGCHLD, &sa, NULL); | 120 sys.sigaction(SIGCHLD, &sa, NULL); |
121 | 121 |
122 // Set up SEGV handler for dealing with RDTSC instructions, system calls | 122 // Set up SEGV handler for dealing with RDTSC instructions, system calls |
123 // that have been rewritten to use INT0, and for sigpending() emulation. | 123 // that have been rewritten to use INT0, and for sigpending() emulation. |
124 sa.sa_handler_ = segv(); | 124 sa.sa_sigaction_ = segv(); |
| 125 sa.sa_flags = SA_SIGINFO; |
125 sys.sigaction(SIGSEGV, &sa, NULL); | 126 sys.sigaction(SIGSEGV, &sa, NULL); |
126 | 127 |
127 // Unblock SIGSEGV and SIGCHLD | 128 // Unblock SIGSEGV and SIGCHLD |
128 SysCalls::kernel_sigset_t mask; | 129 SysCalls::kernel_sigset_t mask; |
129 memset(&mask, 0x00, sizeof(mask)); | 130 memset(&mask, 0x00, sizeof(mask)); |
130 mask.sig[0] |= (1 << (SIGSEGV - 1)) | (1 << (SIGCHLD - 1)); | 131 mask.sig[0] |= (1 << (SIGSEGV - 1)) | (1 << (SIGCHLD - 1)); |
131 sys.sigprocmask(SIG_UNBLOCK, &mask, 0); | 132 sys.sigprocmask(SIG_UNBLOCK, &mask, 0); |
132 } | 133 } |
133 | 134 |
134 void (*Sandbox::segv())(int signo) { | 135 void (*Sandbox::segv())(int signo, SysCalls::siginfo *context, void *unused) { |
135 void (*fnc)(int signo); | 136 void (*fnc)(int signo, SysCalls::siginfo *context, void *unused); |
136 asm volatile( | 137 asm volatile( |
137 "call 999f\n" | 138 "call 999f\n" |
138 #if defined(__x86_64__) | 139 #if defined(__x86_64__) |
139 // Inspect instruction at the point where the segmentation fault | 140 // Inspect instruction at the point where the segmentation fault |
140 // happened. If it is RDTSC, forward the request to the trusted | 141 // happened. If it is RDTSC, forward the request to the trusted |
141 // thread. | 142 // thread. |
142 "mov $-3, %%r14\n" // request for RDTSC | 143 "mov $-3, %%r14\n" // request for RDTSC |
143 "mov 0xB0(%%rsp), %%r15\n" // %rip at time of segmentation fault | 144 "mov 0xB0(%%rsp), %%r15\n" // %rip at time of segmentation fault |
144 "cmpw $0x310F, (%%r15)\n" // RDTSC | 145 "cmpw $0x310F, (%%r15)\n" // RDTSC |
145 "jz 0f\n" | 146 "jz 0f\n" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 "jz 7f\n" | 192 "jz 7f\n" |
192 "mov %%rcx, 0xA0(%%rsp)\n" // %rcx at time of segmentation fault | 193 "mov %%rcx, 0xA0(%%rsp)\n" // %rcx at time of segmentation fault |
193 "7:mov %%rax, 0x98(%%rsp)\n" // %rax at time of segmentation fault | 194 "7:mov %%rax, 0x98(%%rsp)\n" // %rax at time of segmentation fault |
194 "jmp 3b\n" | 195 "jmp 3b\n" |
195 | 196 |
196 // If the instruction is INT 0, then this was probably the result | 197 // If the instruction is INT 0, then this was probably the result |
197 // of playground::Library being unable to find a way to safely | 198 // of playground::Library being unable to find a way to safely |
198 // rewrite the system call instruction. Retrieve the CPU register | 199 // rewrite the system call instruction. Retrieve the CPU register |
199 // at the time of the segmentation fault and invoke syscallWrapper(). | 200 // at the time of the segmentation fault and invoke syscallWrapper(). |
200 "8:cmpw $0x00CD, (%%r15)\n" // INT $0x0 | 201 "8:cmpw $0x00CD, (%%r15)\n" // INT $0x0 |
201 "jnz 14f\n" | 202 "jnz 16f\n" |
202 #ifndef NDEBUG | 203 #ifndef NDEBUG |
203 "lea 200f(%%rip), %%rdi\n" | 204 "lea 200f(%%rip), %%rdi\n" |
204 "call playground$debugMessage\n" | 205 "call playground$debugMessage\n" |
205 #endif | 206 #endif |
206 "mov 0x98(%%rsp), %%rax\n" // %rax at time of segmentation fault | 207 "mov 0x98(%%rsp), %%rax\n" // %rax at time of segmentation fault |
207 "mov 0x70(%%rsp), %%rdi\n" // %rdi at time of segmentation fault | 208 "mov 0x70(%%rsp), %%rdi\n" // %rdi at time of segmentation fault |
208 "mov 0x78(%%rsp), %%rsi\n" // %rsi at time of segmentation fault | 209 "mov 0x78(%%rsp), %%rsi\n" // %rsi at time of segmentation fault |
209 "mov 0x90(%%rsp), %%rdx\n" // %rdx at time of segmentation fault | 210 "mov 0x90(%%rsp), %%rdx\n" // %rdx at time of segmentation fault |
210 "mov 0x40(%%rsp), %%r10\n" // %r10 at time of segmentation fault | 211 "mov 0x40(%%rsp), %%r10\n" // %r10 at time of segmentation fault |
211 "mov 0x30(%%rsp), %%r8\n" // %r8 at time of segmentation fault | 212 "mov 0x30(%%rsp), %%r8\n" // %r8 at time of segmentation fault |
(...skipping 20 matching lines...) Expand all Loading... |
232 "jmp 11f\n" | 233 "jmp 11f\n" |
233 "10:cmp $2, %%rdi\n" // %rdi = how (SIG_SETMASK) | 234 "10:cmp $2, %%rdi\n" // %rdi = how (SIG_SETMASK) |
234 "jnz 7b\n" | 235 "jnz 7b\n" |
235 "mov %%rsi, 0x130(%%rsp)\n" // signal mask at time of segmentation fault | 236 "mov %%rsi, 0x130(%%rsp)\n" // signal mask at time of segmentation fault |
236 "11:xor %%rax, %%rax\n" | 237 "11:xor %%rax, %%rax\n" |
237 "test %%rdx, %%rdx\n" // only return old mask, if set is non-NULL | 238 "test %%rdx, %%rdx\n" // only return old mask, if set is non-NULL |
238 "jz 7b\n" | 239 "jz 7b\n" |
239 "mov %%r10, 0(%%rdx)\n" // old_set | 240 "mov %%r10, 0(%%rdx)\n" // old_set |
240 "jmp 7b\n" | 241 "jmp 7b\n" |
241 | 242 |
| 243 // Handle rt_sigreturn() |
| 244 "12:cmp $15, %%rax\n" // NR_rt_sigreturn |
| 245 "jnz 14f\n" |
| 246 "mov 0xA8(%%rsp), %%rsp\n" // %rsp at time of segmentation fault |
| 247 "13:syscall\n" // rt_sigreturn() is unrestricted |
| 248 "mov $66, %%edi\n" // rt_sigreturn() should never return |
| 249 "mov $231, %%eax\n" // NR_exit_group |
| 250 "jmp 13b\n" |
242 | 251 |
243 // Copy signal frame onto new stack. See clone.cc for details | 252 // Copy signal frame onto new stack. See clone.cc for details |
244 "12:cmp $56+0xF000, %%rax\n" // NR_clone + 0xF000 | 253 "14:cmp $56+0xF000, %%rax\n" // NR_clone + 0xF000 |
245 "jnz 13f\n" | 254 "jnz 15f\n" |
246 "mov 0xA8(%%rsp), %%rcx\n" // %rsp at time of segmentation fault | 255 "mov 0xA8(%%rsp), %%rcx\n" // %rsp at time of segmentation fault |
247 "sub %%rsp, %%rcx\n" // %rcx = size of stack frame | 256 "sub %%rsp, %%rcx\n" // %rcx = size of stack frame |
248 "sub $8, %%rcx\n" // skip return address | 257 "sub $8, %%rcx\n" // skip return address |
249 "mov %%rcx, %%rax\n" // return size of signal stack frame | 258 "mov %%rcx, %%rax\n" // return size of signal stack frame |
250 "mov 0(%%rdx), %%rdi\n" // stack for newly clone()'d thread | 259 "mov 0(%%rdx), %%rdi\n" // stack for newly clone()'d thread |
251 "sub %%rcx, %%rdi\n" // copy onto new stack | 260 "sub %%rcx, %%rdi\n" // copy onto new stack |
252 "mov %%rdi, 0(%%rdx)\n" // allocate space on new stack | 261 "mov %%rdi, 0(%%rdx)\n" // allocate space on new stack |
253 "lea 8(%%rsp), %%rsi\n" // copy from current stack | 262 "lea 8(%%rsp), %%rsi\n" // copy from current stack |
254 "cld\n" | 263 "cld\n" |
255 "rep movsb\n" | 264 "rep movsb\n" |
256 "jmp 7b\n" | 265 "jmp 7b\n" |
257 | 266 |
258 // Forward system call to syscallWrapper() | 267 // Forward system call to syscallWrapper() |
259 "13:lea 7b(%%rip), %%rcx\n" | 268 "15:lea 7b(%%rip), %%rcx\n" |
260 "push %%rcx\n" | 269 "push %%rcx\n" |
261 "push 0xB8(%%rsp)\n" // %rip at time of segmentation fault | 270 "push 0xB8(%%rsp)\n" // %rip at time of segmentation fault |
262 "lea playground$syscallWrapper(%%rip), %%rcx\n" | 271 "lea playground$syscallWrapper(%%rip), %%rcx\n" |
263 "jmp *%%rcx\n" | 272 "jmp *%%rcx\n" |
264 | 273 |
265 // This was a genuine segmentation fault. Trigger the kernel's default | 274 // This was a genuine segmentation fault. Trigger the kernel's default |
266 // signal disposition. The only way we can do this from seccomp mode | 275 // signal disposition. The only way we can do this from seccomp mode |
267 // is by blocking the signal and retriggering it. | 276 // is by blocking the signal and retriggering it. |
268 "14:mov $2, %%edi\n" // stderr | 277 "16:mov $2, %%edi\n" // stderr |
269 "lea 300f(%%rip), %%rsi\n" // "Segmentation fault\n" | 278 "lea 300f(%%rip), %%rsi\n" // "Segmentation fault\n" |
270 "mov $301f-300f, %%edx\n" | 279 "mov $301f-300f, %%edx\n" |
271 "mov $1, %%eax\n" // NR_write | 280 "mov $1, %%eax\n" // NR_write |
272 "syscall\n" | 281 "syscall\n" |
273 "orb $4, 0x131(%%rsp)\n" // signal mask at time of segmentation fault | 282 "orb $4, 0x131(%%rsp)\n" // signal mask at time of segmentation fault |
274 "ret\n" | 283 "ret\n" |
275 #elif defined(__i386__) | 284 #elif defined(__i386__) |
276 // Inspect instruction at the point where the segmentation fault | 285 // Inspect instruction at the point where the segmentation fault |
277 // happened. If it is RDTSC, forward the request to the trusted | 286 // happened. If it is RDTSC, forward the request to the trusted |
278 // thread. | 287 // thread. |
279 "mov $-3, %%ebx\n" // request for RDTSC | 288 "mov $-3, %%ebx\n" // request for RDTSC |
280 "mov 0x40(%%esp), %%ebp\n" // %eip at time of segmentation fault | 289 "mov 0xDC(%%esp), %%ebp\n" // %eip at time of segmentation fault |
281 "cmpw $0x310F, (%%ebp)\n" // RDTSC | 290 "cmpw $0x310F, (%%ebp)\n" // RDTSC |
282 "jz 0f\n" | 291 "jz 0f\n" |
283 "cmpw $0x010F, (%%ebp)\n" | 292 "cmpw $0x010F, (%%ebp)\n" // RDTSCP |
284 "jnz 8f\n" | 293 "jnz 9f\n" |
285 "cmpb $0xF9, 2(%%ebp)\n" | 294 "cmpb $0xF9, 2(%%ebp)\n" |
286 "jnz 8f\n" | 295 "jnz 9f\n" |
287 "mov $-4, %%ebx\n" // request for RDTSCP | 296 "mov $-4, %%ebx\n" // request for RDTSCP |
288 "0:" | 297 "0:" |
289 #ifndef NDEBUG | 298 #ifndef NDEBUG |
290 "lea 100f, %%eax\n" | 299 "lea 100f, %%eax\n" |
291 "push %%eax\n" | 300 "push %%eax\n" |
292 "call playground$debugMessage\n" | 301 "call playground$debugMessage\n" |
293 "sub $4, %%esp\n" | 302 "sub $4, %%esp\n" |
294 #else | 303 #else |
295 "sub $8, %%esp\n" | 304 "sub $8, %%esp\n" // allocate buffer for receiving timestamp |
296 #endif | 305 #endif |
297 "push %%ebx\n" | 306 "push %%ebx\n" |
298 "mov %%fs:16, %%ebx\n" // fd = threadFdPub | 307 "mov %%fs:16, %%ebx\n" // fd = threadFdPub |
299 "mov %%esp, %%ecx\n" // buf = %esp | 308 "mov %%esp, %%ecx\n" // buf = %esp |
300 "mov $4, %%edx\n" // len = sizeof(int) | 309 "mov $4, %%edx\n" // len = sizeof(int) |
301 "1:mov %%edx, %%eax\n" // NR_write | 310 "1:mov %%edx, %%eax\n" // NR_write |
302 "int $0x80\n" | 311 "int $0x80\n" |
303 "cmp %%eax, %%edx\n" | 312 "cmp %%eax, %%edx\n" |
304 "jz 5f\n" | 313 "jz 7f\n" |
305 "cmp $-4, %%eax\n" // EINTR | 314 "cmp $-4, %%eax\n" // EINTR |
306 "jz 1b\n" | 315 "jz 1b\n" |
307 "2:add $12, %%esp\n" | 316 "2:add $12, %%esp\n" // remove temporary buffer from stack |
308 "movl $0, 0x34(%%esp)\n" // %eax at time of segmentation fault | 317 "xor %%eax, %%eax\n" |
309 "movl $0, 0x2C(%%esp)\n" // %edx at time of segmentation fault | 318 "movl $0, 0xC8(%%esp)\n" // %edx at time of segmentation fault |
310 "cmpw $0x310F, (%%ebp)\n" // RDTSC | 319 "cmpw $0x310F, (%%ebp)\n" // RDTSC |
311 "jz 3f\n" | 320 "jz 3f\n" |
312 "movl $0, 0x30(%%esp)\n" // %ecx at time of segmentation fault | 321 "movl $0, 0xCC(%%esp)\n" // %ecx at time of segmentation fault |
313 "3:addl $2, 0x40(%%esp)\n" // %eip at time of segmentation fault | 322 "3:mov %%eax, 0xD0(%%esp)\n" // %eax at time of segmentation fault |
314 "mov 0x40(%%esp), %%ebp\n" // %eip at time of segmentation fault | 323 "4:mov 0xDC(%%esp), %%ebp\n" // %eip at time of segmentation fault |
315 "cmpw $0x010F, (%%ebp)\n" // RDTSC | 324 "addl $2, 0xDC(%%esp)\n" // %eip at time of segmentation fault |
316 "jnz 4f\n" | 325 "cmpw $0x010F, (%%ebp)\n" // RDTSCP |
317 "addl $1, 0x40(%%esp)\n" // %eip at time of segmentation fault | 326 "jnz 5f\n" |
318 "4:ret\n" | 327 "addl $1, 0xDC(%%esp)\n" // %eip at time of segmentation fault |
319 "5:mov $12, %%edx\n" // len = 3*sizeof(int) | 328 "5:sub $0x1C8, %%esp\n" // a legacy signal stack is much larger |
320 "6:mov $3, %%eax\n" // NR_read | 329 "mov 0x1CC(%%esp), %%eax\n" // push signal number |
| 330 "push %%eax\n" |
| 331 "lea 0x270(%%esp), %%esi\n" // copy siginfo register values |
| 332 "lea 0x4(%%esp), %%edi\n" // into new location |
| 333 "mov $22, %%ecx\n" |
| 334 "cld\n" |
| 335 "rep movsl\n" |
| 336 "mov 0x2C8(%%esp), %%ebx\n" // copy first half of signal mask |
| 337 "mov %%ebx, 0x54(%%esp)\n" |
| 338 "lea 6f, %%esi\n" // copy "magic" restorer function |
| 339 "push %%esi\n" // push restorer function |
| 340 "lea 0x2D4(%%esp), %%edi\n" // patch up retcode magic numbers |
| 341 "movb $2, %%cl\n" |
| 342 "rep movsl\n" |
| 343 "ret\n" // return to restorer function |
| 344 |
| 345 // The restorer function is sometimes used by gdb as a magic marker to |
| 346 // recognize signal stack frames. Don't change any of the next three |
| 347 // instructions. |
| 348 "6:pop %%eax\n" // remove dummy argument (signo) |
| 349 "mov $119, %%eax\n" // NR_sigreturn |
| 350 "int $0x80\n" |
| 351 "7:mov $12, %%edx\n" // len = 3*sizeof(int) |
| 352 "8:mov $3, %%eax\n" // NR_read |
321 "int $0x80\n" | 353 "int $0x80\n" |
322 "cmp $-4, %%eax\n" // EINTR | 354 "cmp $-4, %%eax\n" // EINTR |
323 "jz 6b\n" | 355 "jz 8b\n" |
324 "cmp %%eax, %%edx\n" | 356 "cmp %%eax, %%edx\n" |
325 "jnz 2b\n" | 357 "jnz 2b\n" |
326 "pop %%eax\n" | 358 "pop %%eax\n" |
327 "pop %%edx\n" | 359 "pop %%edx\n" |
328 "pop %%ecx\n" | 360 "pop %%ecx\n" |
329 "mov %%edx, 0x2C(%%esp)\n" // %edx at time of segmentation fault | 361 "mov %%edx, 0xC8(%%esp)\n" // %edx at time of segmentation fault |
330 "cmpw $0x310F, (%%ebp)\n" // RDTSC | 362 "cmpw $0x310F, (%%ebp)\n" // RDTSC |
331 "jz 7f\n" | 363 "jz 3b\n" |
332 "mov %%ecx, 0x30(%%esp)\n" // %ecx at time of segmentation fault | 364 "mov %%ecx, 0xCC(%%esp)\n" // %ecx at time of segmentation fault |
333 "7:mov %%eax, 0x34(%%esp)\n" // %eax at time of segmentation fault | |
334 "jmp 3b\n" | 365 "jmp 3b\n" |
335 | 366 |
336 // If the instruction is INT 0, then this was probably the result | 367 // If the instruction is INT 0, then this was probably the result |
337 // of playground::Library being unable to find a way to safely | 368 // of playground::Library being unable to find a way to safely |
338 // rewrite the system call instruction. Retrieve the CPU register | 369 // rewrite the system call instruction. Retrieve the CPU register |
339 // at the time of the segmentation fault and invoke syscallWrapper(). | 370 // at the time of the segmentation fault and invoke syscallWrapper(). |
340 "8:cmpw $0x00CD, (%%ebp)\n" // INT $0x0 | 371 "9:cmpw $0x00CD, (%%ebp)\n" // INT $0x0 |
341 "jnz 16f\n" | 372 "jnz 20f\n" |
342 #ifndef NDEBUG | 373 #ifndef NDEBUG |
343 "lea 200f, %%eax\n" | 374 "lea 200f, %%eax\n" |
344 "push %%eax\n" | 375 "push %%eax\n" |
345 "call playground$debugMessage\n" | 376 "call playground$debugMessage\n" |
346 "add $0x4, %%esp\n" | 377 "add $0x4, %%esp\n" |
347 #endif | 378 #endif |
348 "mov 0x34(%%esp), %%eax\n" // %eax at time of segmentation fault | 379 "mov 0xD0(%%esp), %%eax\n" // %eax at time of segmentation fault |
349 "mov 0x28(%%esp), %%ebx\n" // %ebx at time of segmentation fault | 380 "mov 0xC4(%%esp), %%ebx\n" // %ebx at time of segmentation fault |
350 "mov 0x30(%%esp), %%ecx\n" // %ecx at time of segmentation fault | 381 "mov 0xCC(%%esp), %%ecx\n" // %ecx at time of segmentation fault |
351 "mov 0x2C(%%esp), %%edx\n" // %edx at time of segmentation fault | 382 "mov 0xC8(%%esp), %%edx\n" // %edx at time of segmentation fault |
352 "mov 0x1C(%%esp), %%esi\n" // %esi at time of segmentation fault | 383 "mov 0xB8(%%esp), %%esi\n" // %esi at time of segmentation fault |
353 "mov 0x18(%%esp), %%edi\n" // %edi at time of segmentation fault | 384 "mov 0xB4(%%esp), %%edi\n" // %edi at time of segmentation fault |
354 "mov 0x20(%%esp), %%ebp\n" // %ebp at time of segmentation fault | 385 "mov 0xB2(%%esp), %%ebp\n" // %ebp at time of segmentation fault |
355 | 386 |
356 // Handle sigprocmask() and rt_sigprocmask() | 387 // Handle sigprocmask() and rt_sigprocmask() |
357 "cmp $175, %%eax\n" // NR_rt_sigprocmask | 388 "cmp $175, %%eax\n" // NR_rt_sigprocmask |
358 "jnz 9f\n" | 389 "jnz 10f\n" |
359 "mov $-22, %%eax\n" // -EINVAL | 390 "mov $-22, %%eax\n" // -EINVAL |
360 "cmp $8, %%esi\n" // %esi = sigsetsize (8 bytes = 64 signals) | 391 "cmp $8, %%esi\n" // %esi = sigsetsize (8 bytes = 64 signals) |
361 "jl 7b\n" | 392 "jl 3b\n" |
362 "jmp 10f\n" | 393 "jmp 11f\n" |
363 "9:cmp $126, %%eax\n" // NR_sigprocmask | 394 "10:cmp $126, %%eax\n" // NR_sigprocmask |
364 "jnz 14f\n" | 395 "jnz 15f\n" |
365 "mov $-22, %%eax\n" | 396 "mov $-22, %%eax\n" |
366 "10:mov 0x58(%%esp), %%edi\n" // signal mask at time of segmentation fault | 397 "11:mov 0xFC(%%esp), %%edi\n" // signal mask at time of segmentation fault |
367 "mov 0x5C(%%esp), %%ebp\n" | 398 "mov 0x100(%%esp), %%ebp\n" |
368 "test %%ecx, %%ecx\n" // only set mask, if set is non-NULL | 399 "test %%ecx, %%ecx\n" // only set mask, if set is non-NULL |
369 "jz 13f\n" | 400 "jz 14f\n" |
370 "mov 0(%%ecx), %%esi\n" | 401 "mov 0(%%ecx), %%esi\n" |
371 "mov 4(%%ecx), %%ecx\n" | 402 "mov 4(%%ecx), %%ecx\n" |
372 "cmp $0, %%ebx\n" // %ebx = how (SIG_BLOCK) | 403 "cmp $0, %%ebx\n" // %ebx = how (SIG_BLOCK) |
373 "jnz 11f\n" | |
374 "or %%esi, 0x58(%%esp)\n" // signal mask at time of segmentation fault | |
375 "or %%ecx, 0x5C(%%esp)\n" | |
376 "jmp 13f\n" | |
377 "11:cmp $1, %%ebx\n" // %ebx = how (SIG_UNBLOCK) | |
378 "jnz 12f\n" | 404 "jnz 12f\n" |
| 405 "or %%esi, 0xFC(%%esp)\n" // signal mask at time of segmentation fault |
| 406 "or %%ecx, 0x100(%%esp)\n" |
| 407 "jmp 14f\n" |
| 408 "12:cmp $1, %%ebx\n" // %ebx = how (SIG_UNBLOCK) |
| 409 "jnz 13f\n" |
379 "xor $-1, %%esi\n" | 410 "xor $-1, %%esi\n" |
380 "xor $-1, %%ecx\n" | 411 "xor $-1, %%ecx\n" |
381 "and %%esi, 0x58(%%esp)\n" // signal mask at time of segmentation fault | 412 "and %%esi, 0xFC(%%esp)\n" // signal mask at time of segmentation fault |
382 "and %%ecx, 0x5C(%%esp)\n" | 413 "and %%ecx, 0x100(%%esp)\n" |
383 "jmp 13f\n" | 414 "jmp 14f\n" |
384 "12:cmp $2, %%ebx\n" // %ebx = how (SIG_SETMASK) | 415 "13:cmp $2, %%ebx\n" // %ebx = how (SIG_SETMASK) |
385 "jnz 7b\n" | 416 "jnz 3b\n" |
386 "mov %%esi, 0x58(%%esp)\n" // signal mask at time of segmentation fault | 417 "mov %%esi, 0xFC(%%esp)\n" // signal mask at time of segmentation fault |
387 "mov %%ecx, 0x5C(%%esp)\n" | 418 "mov %%ecx, 0x100(%%esp)\n" |
388 "13:xor %%eax, %%eax\n" | 419 "14:xor %%eax, %%eax\n" |
389 "test %%edx, %%edx\n" // only return old mask, if set is non-NULL | 420 "test %%edx, %%edx\n" // only return old mask, if set is non-NULL |
390 "jz 7b\n" | 421 "jz 3b\n" |
391 "mov %%edi, 0(%%edx)\n" // old_set | 422 "mov %%edi, 0(%%edx)\n" // old_set |
392 "mov %%ebp, 4(%%edx)\n" | 423 "mov %%ebp, 4(%%edx)\n" |
393 "jmp 7b\n" | 424 "jmp 3b\n" |
394 | 425 |
395 // Copy signal frame onto new stack. See clone.cc for details | 426 // Handle sigreturn() and rt_sigreturn() |
396 "14:cmp $120+0xF000, %%eax\n" // NR_clone + 0xF000 | 427 // See syscall.cc for a discussion on how we can emulate rt_sigreturn() |
397 "jnz 15f\n" | 428 // by calling sigreturn() with a suitably adjusted stack. |
398 "mov 0x24(%%esp), %%ecx\n" // %esp at time of segmentation fault | 429 "15:cmp $119, %%eax\n" // NR_sigreturn |
399 "sub %%esp, %%ecx\n" // %ecx = size of stack frame | 430 "jnz 17f\n" |
400 "sub $8, %%ecx\n" // skip return address and dummy | 431 "mov 0xC0(%%esp), %%esp\n" // %esp at time of segmentation fault |
401 "mov %%ecx, %%eax\n" // return size of signal stack frame | 432 "16:int $0x80\n" // sigreturn() is unrestricted |
| 433 "17:cmp $173, %%eax\n" // NR_rt_sigreturn |
| 434 "jnz 18f\n" |
| 435 "mov 0xC0(%%esp), %%esp\n" // %esp at time of segmentation fault |
| 436 "sub $4, %%esp\n" // add fake return address |
| 437 "jmp 4b\n" |
| 438 |
| 439 // Copy signal frame onto new stack. In the process, we have to convert |
| 440 // it from an RT signal frame to a legacy signal frame. |
| 441 // See clone.cc for details |
| 442 "18:cmp $120+0xF000, %%eax\n" // NR_clone + 0xF000 |
| 443 "jnz 19f\n" |
| 444 "mov 0xC0(%%esp), %%ecx\n" // %esp at time of segmentation fault |
| 445 "sub %%esp, %%ecx\n" // %ecx = size of RT stack frame |
| 446 "mov %%ecx, %%eax\n" |
| 447 "add $0x1C8, %%eax\n" // adjust for size of legacy stack frame |
| 448 "sub $0x100, %%ecx\n" |
402 "mov 0(%%edx), %%edi\n" // stack for newly clone()'d thread | 449 "mov 0(%%edx), %%edi\n" // stack for newly clone()'d thread |
403 "sub %%ecx, %%edi\n" // copy onto new stack | 450 "sub %%ecx, %%edi\n" // copy onto new stack |
| 451 "lea 0x100(%%esp), %%esi\n" |
| 452 "cld\n" |
| 453 "rep movsb\n" // copy parts of RT stack(sigmask, FP state) |
| 454 "mov 0xF0(%%esp), %%ebx\n" // adjust pointer to fpstate |
| 455 "sub %%esi, %%ebx\n" |
| 456 "add %%edi, %%ebx\n" |
| 457 "sub %%eax, %%edi\n" |
404 "mov %%edi, 0(%%edx)\n" // allocate space on new stack | 458 "mov %%edi, 0(%%edx)\n" // allocate space on new stack |
405 "lea 8(%%esp), %%esi\n" // copy from current stack | 459 "lea 0xA4(%%esp), %%esi\n" // copy sigcontext from current stack |
406 "cld\n" | 460 "mov $0x16, %%ecx\n" |
407 "rep movsb\n" | 461 "rep movsl\n" |
408 "jmp 7b\n" | 462 "mov %%ebx, -0xC(%%edi)\n" // set pointer to fpstate |
| 463 "mov 0xFC(%%esp), %%ebx\n" // copy first half of signal mask |
| 464 "mov %%ebx, -0x8(%%edi)\n" |
| 465 "mov %%eax, -0x2C(%%edi)\n" // return size of stack frame in %%eax |
| 466 "addl $2, -0x20(%%edi)\n" // adjust %eip |
| 467 "mov 0(%%edx), %%esp\n" |
| 468 "mov $119, %%eax\n" // NR_sigreturn |
| 469 "int $0x80\n" |
409 | 470 |
410 // Forward system call to syscallWrapper() | 471 // Forward system call to syscallWrapper() |
411 "15:call playground$syscallWrapper\n" | 472 "19:call playground$syscallWrapper\n" |
412 "jmp 7b\n" | 473 "jmp 3b\n" |
413 | 474 |
414 // This was a genuine segmentation fault. Trigger the kernel's default | 475 // This was a genuine segmentation fault. Trigger the kernel's default |
415 // signal disposition. The only way we can do this from seccomp mode | 476 // signal disposition. The only way we can do this from seccomp mode |
416 // is by blocking the signal and retriggering it. | 477 // is by blocking the signal and retriggering it. |
417 "16:mov $2, %%ebx\n" // stderr | 478 "20:mov $2, %%ebx\n" // stderr |
418 "lea 300f, %%ecx\n" // "Segmentation fault\n" | 479 "lea 300f, %%ecx\n" // "Segmentation fault\n" |
419 "mov $301f-300f, %%edx\n" | 480 "mov $301f-300f, %%edx\n" |
420 "mov $4, %%eax\n" // NR_write | 481 "mov $4, %%eax\n" // NR_write |
421 "int $0x80\n" | 482 "int $0x80\n" |
422 "orb $4, 0x59(%%esp)\n" // signal mask at time of segmentation fault | 483 "orb $4, 0xFD(%%esp)\n" // signal mask at time of segmentation fault |
423 "ret\n" | 484 "jmp 4b\n" |
424 #else | 485 #else |
425 #error Unsupported target platform | 486 #error Unsupported target platform |
426 #endif | 487 #endif |
427 ".pushsection \".rodata\"\n" | 488 ".pushsection \".rodata\"\n" |
428 #ifndef NDEBUG | 489 #ifndef NDEBUG |
429 "100:.asciz \"RDTSC(P): Executing handler\\n\"\n" | 490 "100:.asciz \"RDTSC(P): Executing handler\\n\"\n" |
430 "200:.asciz \"INT $0x0: Executing handler\\n\"\n" | 491 "200:.asciz \"INT $0x0: Executing handler\\n\"\n" |
431 #endif | 492 #endif |
432 "300:.ascii \"Segmentation fault\\n\"\n" | 493 "300:.ascii \"Segmentation fault\\n\"\n" |
433 "301:\n" | 494 "301:\n" |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 // Creating the trusted thread enables sandboxing | 699 // Creating the trusted thread enables sandboxing |
639 createTrustedThread(processFdPub_, cloneFdPub_, secureMem); | 700 createTrustedThread(processFdPub_, cloneFdPub_, secureMem); |
640 | 701 |
641 // We can no longer check for sandboxing support at this point, but we also | 702 // We can no longer check for sandboxing support at this point, but we also |
642 // know for a fact that it is available (as we just turned it on). So update | 703 // know for a fact that it is available (as we just turned it on). So update |
643 // the status to reflect this information. | 704 // the status to reflect this information. |
644 status_ = STATUS_ENABLED; | 705 status_ = STATUS_ENABLED; |
645 } | 706 } |
646 | 707 |
647 } // namespace | 708 } // namespace |
OLD | NEW |