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 "sandbox_impl.h" | 5 #include "sandbox_impl.h" |
6 | 6 |
7 #include "library.h" | 7 #include "library.h" |
8 #include "syscall_entrypoint.h" | 8 #include "syscall_entrypoint.h" |
9 #include "syscall_table.h" | 9 #include "syscall_table.h" |
10 | 10 |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
348 ".popsection\n" | 348 ".popsection\n" |
349 #elif defined(__i386__) | 349 #elif defined(__i386__) |
350 // Inspect instruction at the point where the segmentation fault | 350 // Inspect instruction at the point where the segmentation fault |
351 // happened. If it is RDTSC, forward the request to the trusted | 351 // happened. If it is RDTSC, forward the request to the trusted |
352 // thread. | 352 // thread. |
353 "mov $-3, %%ebx\n" // request for RDTSC | 353 "mov $-3, %%ebx\n" // request for RDTSC |
354 "mov 0xDC(%%esp), %%ebp\n" // %eip at time of segmentation fault | 354 "mov 0xDC(%%esp), %%ebp\n" // %eip at time of segmentation fault |
355 "cmpw $0x310F, (%%ebp)\n" // RDTSC | 355 "cmpw $0x310F, (%%ebp)\n" // RDTSC |
356 "jz 0f\n" | 356 "jz 0f\n" |
357 "cmpw $0x010F, (%%ebp)\n" // RDTSCP | 357 "cmpw $0x010F, (%%ebp)\n" // RDTSCP |
358 "jnz 9f\n" | 358 "jnz 10f\n" |
359 "cmpb $0xF9, 2(%%ebp)\n" | 359 "cmpb $0xF9, 2(%%ebp)\n" |
360 "jnz 9f\n" | 360 "jnz 10f\n" |
361 "mov $-4, %%ebx\n" // request for RDTSCP | 361 "mov $-4, %%ebx\n" // request for RDTSCP |
362 "0:" | 362 "0:" |
363 #ifndef NDEBUG | 363 #ifndef NDEBUG |
364 "lea 100f, %%eax\n" | 364 "lea 100f, %%eax\n" |
365 "push %%eax\n" | 365 "push %%eax\n" |
366 "call playground$debugMessage\n" | 366 "call playground$debugMessage\n" |
367 "sub $4, %%esp\n" | 367 "sub $4, %%esp\n" |
368 #else | 368 #else |
369 "sub $8, %%esp\n" // allocate buffer for receiving timestamp | 369 "sub $8, %%esp\n" // allocate buffer for receiving timestamp |
370 #endif | 370 #endif |
371 "push %%ebx\n" | 371 "push %%ebx\n" |
372 "mov %%fs:16, %%ebx\n" // fd = threadFdPub | 372 "mov %%fs:16, %%ebx\n" // fd = threadFdPub |
373 "mov %%esp, %%ecx\n" // buf = %esp | 373 "mov %%esp, %%ecx\n" // buf = %esp |
374 "mov $4, %%edx\n" // len = sizeof(int) | 374 "mov $4, %%edx\n" // len = sizeof(int) |
375 "1:mov %%edx, %%eax\n" // NR_write | 375 "1:mov %%edx, %%eax\n" // NR_write |
376 "int $0x80\n" | 376 "int $0x80\n" |
377 "cmp %%eax, %%edx\n" | 377 "cmp %%eax, %%edx\n" |
378 "jz 7f\n" | 378 "jz 8f\n" |
379 "cmp $-4, %%eax\n" // EINTR | 379 "cmp $-4, %%eax\n" // EINTR |
380 "jz 1b\n" | 380 "jz 1b\n" |
381 "2:add $12, %%esp\n" // remove temporary buffer from stack | 381 "2:add $12, %%esp\n" // remove temporary buffer from stack |
382 "xor %%eax, %%eax\n" | 382 "xor %%eax, %%eax\n" |
383 "movl $0, 0xC8(%%esp)\n" // %edx at time of segmentation fault | 383 "movl $0, 0xC8(%%esp)\n" // %edx at time of segmentation fault |
384 "cmpw $0x310F, (%%ebp)\n" // RDTSC | 384 "cmpw $0x310F, (%%ebp)\n" // RDTSC |
385 "jz 3f\n" | 385 "jz 3f\n" |
386 "movl $0, 0xCC(%%esp)\n" // %ecx at time of segmentation fault | 386 "movl $0, 0xCC(%%esp)\n" // %ecx at time of segmentation fault |
387 "3:mov %%eax, 0xD0(%%esp)\n" // %eax at time of segmentation fault | 387 "3:mov %%eax, 0xD0(%%esp)\n" // %eax at time of segmentation fault |
388 "4:mov 0xDC(%%esp), %%ebp\n" // %eip at time of segmentation fault | 388 "4:mov 0xDC(%%esp), %%ebp\n" // %eip at time of segmentation fault |
389 "addl $2, 0xDC(%%esp)\n" // %eip at time of segmentation fault | 389 "addl $2, 0xDC(%%esp)\n" // %eip at time of segmentation fault |
390 "cmpw $0x010F, (%%ebp)\n" // RDTSCP | 390 "cmpw $0x010F, (%%ebp)\n" // RDTSCP |
391 "jnz 5f\n" | 391 "jnz 5f\n" |
392 "addl $1, 0xDC(%%esp)\n" // %eip at time of segmentation fault | 392 "addl $1, 0xDC(%%esp)\n" // %eip at time of segmentation fault |
393 "5:sub $0x1C8, %%esp\n" // a legacy signal stack is much larger | 393 "5:add $0x4, %%esp\n" |
394 "6:sub $0x1CC, %%esp\n" // a legacy signal stack is much larger | |
394 "mov 0x1CC(%%esp), %%eax\n" // push signal number | 395 "mov 0x1CC(%%esp), %%eax\n" // push signal number |
395 "push %%eax\n" | 396 "push %%eax\n" |
396 "lea 0x270(%%esp), %%esi\n" // copy siginfo register values | 397 "lea 0x270(%%esp), %%esi\n" // copy siginfo register values |
397 "lea 0x4(%%esp), %%edi\n" // into new location | 398 "lea 0x4(%%esp), %%edi\n" // into new location |
398 "mov $22, %%ecx\n" | 399 "mov $22, %%ecx\n" |
399 "cld\n" | 400 "cld\n" |
400 "rep movsl\n" | 401 "rep movsl\n" |
401 "mov 0x2C8(%%esp), %%ebx\n" // copy first half of signal mask | 402 "mov 0x2C8(%%esp), %%ebx\n" // copy first half of signal mask |
402 "mov %%ebx, 0x54(%%esp)\n" | 403 "mov %%ebx, 0x54(%%esp)\n" |
403 "lea 6f, %%esi\n" // copy "magic" restorer function | 404 "7:pop %%eax\n" // remove dummy argument (signo) |
404 "push %%esi\n" // push restorer function | |
405 "lea 0x2D4(%%esp), %%edi\n" // patch up retcode magic numbers | |
406 "movb $2, %%cl\n" | |
407 "rep movsl\n" | |
408 "ret\n" // return to restorer function | |
409 | |
410 // The restorer function is sometimes used by gdb as a magic marker to | |
411 // recognize signal stack frames. Don't change any of the next three | |
412 // instructions. | |
413 "6:pop %%eax\n" // remove dummy argument (signo) | |
414 "mov $119, %%eax\n" // NR_sigreturn | 405 "mov $119, %%eax\n" // NR_sigreturn |
415 "int $0x80\n" | 406 "int $0x80\n" |
416 "7:mov $12, %%edx\n" // len = 3*sizeof(int) | 407 "8:mov $12, %%edx\n" // len = 3*sizeof(int) |
417 "8:mov $3, %%eax\n" // NR_read | 408 "9:mov $3, %%eax\n" // NR_read |
418 "int $0x80\n" | 409 "int $0x80\n" |
419 "cmp $-4, %%eax\n" // EINTR | 410 "cmp $-4, %%eax\n" // EINTR |
420 "jz 8b\n" | 411 "jz 9b\n" |
421 "cmp %%eax, %%edx\n" | 412 "cmp %%eax, %%edx\n" |
422 "jnz 2b\n" | 413 "jnz 2b\n" |
423 "pop %%eax\n" | 414 "pop %%eax\n" |
424 "pop %%edx\n" | 415 "pop %%edx\n" |
425 "pop %%ecx\n" | 416 "pop %%ecx\n" |
426 "mov %%edx, 0xC8(%%esp)\n" // %edx at time of segmentation fault | 417 "mov %%edx, 0xC8(%%esp)\n" // %edx at time of segmentation fault |
427 "cmpw $0x310F, (%%ebp)\n" // RDTSC | 418 "cmpw $0x310F, (%%ebp)\n" // RDTSC |
428 "jz 3b\n" | 419 "jz 3b\n" |
429 "mov %%ecx, 0xCC(%%esp)\n" // %ecx at time of segmentation fault | 420 "mov %%ecx, 0xCC(%%esp)\n" // %ecx at time of segmentation fault |
430 "jmp 3b\n" | 421 "jmp 3b\n" |
431 | 422 |
432 // If the instruction is INT 0, then this was probably the result | 423 // If the instruction is INT 0, then this was probably the result |
433 // of playground::Library being unable to find a way to safely | 424 // of playground::Library being unable to find a way to safely |
434 // rewrite the system call instruction. Retrieve the CPU register | 425 // rewrite the system call instruction. Retrieve the CPU register |
435 // at the time of the segmentation fault and invoke | 426 // at the time of the segmentation fault and invoke |
436 // syscallEntryPointWithFrame(). | 427 // syscallEntryPointWithFrame(). |
437 "9:cmpw $0x00CD, (%%ebp)\n" // INT $0x0 | 428 "10:cmpw $0x00CD, (%%ebp)\n" // INT $0x0 |
438 "jnz 20f\n" | 429 "jnz 20f\n" |
439 #ifndef NDEBUG | 430 #ifndef NDEBUG |
440 "lea 200f, %%eax\n" | 431 "lea 200f, %%eax\n" |
441 "push %%eax\n" | 432 "push %%eax\n" |
442 "call playground$debugMessage\n" | 433 "call playground$debugMessage\n" |
443 "add $0x4, %%esp\n" | 434 "add $0x4, %%esp\n" |
444 #endif | 435 #endif |
445 "mov 0xD0(%%esp), %%eax\n" // %eax at time of segmentation fault | 436 "mov 0xD0(%%esp), %%eax\n" // %eax at time of segmentation fault |
446 "mov 0xC4(%%esp), %%ebx\n" // %ebx at time of segmentation fault | 437 "mov 0xC4(%%esp), %%ebx\n" // %ebx at time of segmentation fault |
447 "mov 0xCC(%%esp), %%ecx\n" // %ecx at time of segmentation fault | 438 "mov 0xCC(%%esp), %%ecx\n" // %ecx at time of segmentation fault |
448 "mov 0xC8(%%esp), %%edx\n" // %edx at time of segmentation fault | 439 "mov 0xC8(%%esp), %%edx\n" // %edx at time of segmentation fault |
449 "mov 0xB8(%%esp), %%esi\n" // %esi at time of segmentation fault | 440 "mov 0xB8(%%esp), %%esi\n" // %esi at time of segmentation fault |
450 "mov 0xB4(%%esp), %%edi\n" // %edi at time of segmentation fault | 441 "mov 0xB4(%%esp), %%edi\n" // %edi at time of segmentation fault |
451 "mov 0xB2(%%esp), %%ebp\n" // %ebp at time of segmentation fault | 442 "mov 0xB2(%%esp), %%ebp\n" // %ebp at time of segmentation fault |
452 | 443 |
453 // Handle sigprocmask() and rt_sigprocmask() | 444 // Handle sigprocmask() and rt_sigprocmask() |
454 "cmp $175, %%eax\n" // NR_rt_sigprocmask | 445 "cmp $175, %%eax\n" // NR_rt_sigprocmask |
455 "jnz 10f\n" | 446 "jnz 11f\n" |
456 "mov $-22, %%eax\n" // -EINVAL | 447 "mov $-22, %%eax\n" // -EINVAL |
457 "cmp $8, %%esi\n" // %esi = sigsetsize (8 bytes = 64 signals) | 448 "cmp $8, %%esi\n" // %esi = sigsetsize (8 bytes = 64 signals) |
458 "jl 3b\n" | 449 "jl 3b\n" |
459 "jmp 11f\n" | 450 "jmp 12f\n" |
460 "10:cmp $126, %%eax\n" // NR_sigprocmask | 451 "11:cmp $126, %%eax\n" // NR_sigprocmask |
461 "jnz 15f\n" | 452 "jnz 16f\n" |
462 "mov $-22, %%eax\n" | 453 "mov $-22, %%eax\n" |
463 "11:mov 0xFC(%%esp), %%edi\n" // signal mask at time of segmentation fault | 454 "12:mov 0xFC(%%esp), %%edi\n" // signal mask at time of segmentation fault |
464 "mov 0x100(%%esp), %%ebp\n" | 455 "mov 0x100(%%esp), %%ebp\n" |
465 "test %%ecx, %%ecx\n" // only set mask, if set is non-NULL | 456 "test %%ecx, %%ecx\n" // only set mask, if set is non-NULL |
466 "jz 14f\n" | 457 "jz 15f\n" |
467 "mov 0(%%ecx), %%esi\n" | 458 "mov 0(%%ecx), %%esi\n" |
468 "mov 4(%%ecx), %%ecx\n" | 459 "mov 4(%%ecx), %%ecx\n" |
469 "cmp $0, %%ebx\n" // %ebx = how (SIG_BLOCK) | 460 "cmp $0, %%ebx\n" // %ebx = how (SIG_BLOCK) |
470 "jnz 12f\n" | 461 "jnz 13f\n" |
471 "or %%esi, 0xFC(%%esp)\n" // signal mask at time of segmentation fault | 462 "or %%esi, 0xFC(%%esp)\n" // signal mask at time of segmentation fault |
472 "or %%ecx, 0x100(%%esp)\n" | 463 "or %%ecx, 0x100(%%esp)\n" |
473 "jmp 14f\n" | 464 "jmp 15f\n" |
474 "12:cmp $1, %%ebx\n" // %ebx = how (SIG_UNBLOCK) | 465 "13:cmp $1, %%ebx\n" // %ebx = how (SIG_UNBLOCK) |
475 "jnz 13f\n" | 466 "jnz 14f\n" |
476 "xor $-1, %%esi\n" | 467 "xor $-1, %%esi\n" |
477 "xor $-1, %%ecx\n" | 468 "xor $-1, %%ecx\n" |
478 "and %%esi, 0xFC(%%esp)\n" // signal mask at time of segmentation fault | 469 "and %%esi, 0xFC(%%esp)\n" // signal mask at time of segmentation fault |
479 "and %%ecx, 0x100(%%esp)\n" | 470 "and %%ecx, 0x100(%%esp)\n" |
480 "jmp 14f\n" | 471 "jmp 15f\n" |
481 "13:cmp $2, %%ebx\n" // %ebx = how (SIG_SETMASK) | 472 "14:cmp $2, %%ebx\n" // %ebx = how (SIG_SETMASK) |
482 "jnz 3b\n" | 473 "jnz 3b\n" |
483 "mov %%esi, 0xFC(%%esp)\n" // signal mask at time of segmentation fault | 474 "mov %%esi, 0xFC(%%esp)\n" // signal mask at time of segmentation fault |
484 "mov %%ecx, 0x100(%%esp)\n" | 475 "mov %%ecx, 0x100(%%esp)\n" |
485 "14:xor %%eax, %%eax\n" | 476 "15:xor %%eax, %%eax\n" |
486 "test %%edx, %%edx\n" // only return old mask, if set is non-NULL | 477 "test %%edx, %%edx\n" // only return old mask, if set is non-NULL |
487 "jz 3b\n" | 478 "jz 3b\n" |
488 "mov %%edi, 0(%%edx)\n" // old_set | 479 "mov %%edi, 0(%%edx)\n" // old_set |
489 "mov %%ebp, 4(%%edx)\n" | 480 "mov %%ebp, 4(%%edx)\n" |
490 "jmp 3b\n" | 481 "jmp 3b\n" |
491 | 482 |
492 // Handle sigreturn() and rt_sigreturn() | 483 // Handle sigreturn() and rt_sigreturn() |
493 // See syscall.cc for a discussion on how we can emulate rt_sigreturn() | 484 // See syscall.cc for a discussion on how we can emulate rt_sigreturn() |
494 // by calling sigreturn() with a suitably adjusted stack. | 485 // by calling sigreturn() with a suitably adjusted stack. |
495 "15:cmp $119, %%eax\n" // NR_sigreturn | 486 "16:cmp $119, %%eax\n" // NR_sigreturn |
496 "jnz 17f\n" | 487 "jnz 17f\n" |
497 "mov 0xC0(%%esp), %%esp\n" // %esp at time of segmentation fault | 488 "mov 0xC0(%%esp), %%esp\n" // %esp at time of segmentation fault |
498 "16:int $0x80\n" // sigreturn() is unrestricted | 489 "int $0x80\n" // sigreturn() is unrestricted |
499 "17:cmp $173, %%eax\n" // NR_rt_sigreturn | 490 "17:cmp $173, %%eax\n" // NR_rt_sigreturn |
500 "jnz 18f\n" | 491 "jnz 18f\n" |
501 "mov 0xC0(%%esp), %%esp\n" // %esp at time of segmentation fault | 492 "mov 0xC0(%%esp), %%esp\n" // %esp at time of segmentation fault |
502 "sub $4, %%esp\n" // add fake return address | 493 "sub $4, %%esp\n" // add fake return address |
503 "jmp 4b\n" | 494 "jmp 4b\n" |
504 | 495 |
505 // Copy signal frame onto new stack. In the process, we have to convert | 496 // Copy signal frame onto new stack. In the process, we have to convert |
506 // it from an RT signal frame to a legacy signal frame. | 497 // it from an RT signal frame to a legacy signal frame. |
507 // See clone.cc for details | 498 // See clone.cc for details |
508 "18:cmp $120+0xF000, %%eax\n" // NR_clone + 0xF000 | 499 "18:cmp $120+0xF000, %%eax\n" // NR_clone + 0xF000 |
509 "jnz 19f\n" | 500 "jnz 19f\n" |
510 "lea -0x1C8(%%esp), %%eax\n"// retain stack frame upon returning | 501 "lea -0x1C8(%%esp), %%eax\n"// retain stack frame upon returning |
511 "mov %%eax, 0xC0(%%esp)\n" // %esp at time of segmentation fault | 502 "mov %%eax, 0xC0(%%esp)\n" // %esp at time of segmentation fault |
512 "jmp 3b\n" | 503 "jmp 3b\n" |
513 | 504 |
514 // Forward system call to syscallEntryPointWithFrame() | 505 // Forward system call to syscallEntryPointWithFrame() |
515 "19:push $3b\n" | 506 "19:push $3b\n" |
516 "push 0xE0(%%esp)\n" // %eip at time of segmentation fault | 507 "push 0xE0(%%esp)\n" // %eip at time of segmentation fault |
517 "jmp playground$syscallEntryPointWithFrame\n" | 508 "jmp playground$syscallEntryPointWithFrame\n" |
518 | 509 |
510 // This was a genuine segmentation fault. Check Sandbox::sa_segv_ for | |
511 // what we are supposed to do. | |
519 // In order to implement SA_NODEFER, we have to keep track of recursive | 512 // In order to implement SA_NODEFER, we have to keep track of recursive |
520 // calls to SIGSEGV handlers. This means we have to increment a counter | 513 // calls to SIGSEGV handlers. This means we have to increment a counter |
521 // before calling the user's signal handler, and decrement it on | 514 // before calling the user's signal handler, and decrement it on |
522 // leaving the user's signal handler. | 515 // leaving the user's signal handler. |
523 // Some signal handlers look at the return address of the signal | |
524 // stack, and more importantly "gdb" uses the call to {,rt_}sigreturn() | |
525 // as a magic signature when doing stacktraces. So, we have to use | |
526 // a little more unusual code to regain control after the user's | |
527 // signal handler is done. We adjust the return address to point to | |
528 // non-executable memory. And when we trigger another SEGV we pop the | |
529 // extraneous signal frame and then call sigreturn(). | |
530 // N.B. We currently do not correctly adjust the SEGV counter, if the | 516 // N.B. We currently do not correctly adjust the SEGV counter, if the |
531 // user's signal handler exits in way other than by returning (e.g. by | 517 // user's signal handler exits in way other than by returning (e.g. by |
532 // directly calling {,rt_}sigreturn(), or by calling siglongjmp()). | 518 // directly calling {,rt_}sigreturn(), or by calling siglongjmp()). |
533 "20:lea 30f, %%edi\n" // rt-style restorer function | 519 // N.B. On i386, we don't have any guarantees that NX protection works. |
534 "lea 31f, %%esi\n" // legacy restorer function | 520 // So, we don't even attempt to fake a correct restorer function. Some |
535 "cmp %%ebp, %%edi\n" // check if returning from user's handler | 521 // callers might be confused by this and will need fixing for running |
536 "jnz 21f\n" | 522 // inside of the seccomp sandbox. |
537 "decl %%fs:0x1040-0x58\n" // decrement SEGV recursion counter | 523 "20:lea playground$sa_segv, %%eax\n" |
538 "mov 0xC0(%%esp), %%esp\n" // %esp at time of segmentation fault | |
539 "jmp 29f\n" | |
540 "21:cmp %%ebp, %%esi\n" // check if returning from user's handler | |
541 "jnz 22f\n" | |
542 "decl %%fs:0x1040-0x58\n" // decrement SEGV recursion counter | |
543 "mov 0xC0(%%esp), %%esp\n" // %esp at time of segmentation fault | |
544 "jmp 6b\n" | |
545 | |
546 // This was a genuine segmentation fault. Check Sandbox::sa_segv_ for | |
547 // what we are supposed to do. | |
548 "22:lea playground$sa_segv, %%eax\n" | |
549 "cmp $0, 0(%%eax)\n" // SIG_DFL | 524 "cmp $0, 0(%%eax)\n" // SIG_DFL |
550 "jz 23f\n" | 525 "jz 21f\n" |
551 "cmp $1, 0(%%eax)\n" // SIG_IGN | 526 "cmp $1, 0(%%eax)\n" // SIG_IGN |
552 "jnz 24f\n" // can't really ignore synchronous signals | 527 "jnz 22f\n" // can't really ignore synchronous signals |
553 | 528 |
554 // Trigger the kernel's default signal disposition. The only way we can | 529 // Trigger the kernel's default signal disposition. The only way we can |
555 // do this from seccomp mode is by blocking the signal and retriggering | 530 // do this from seccomp mode is by blocking the signal and retriggering |
556 // it. | 531 // it. |
557 "23:orb $4, 0xFD(%%esp)\n" // signal mask at time of segmentation fault | 532 "21:orb $4, 0xFD(%%esp)\n" // signal mask at time of segmentation fault |
558 "jmp 5b\n" | 533 "jmp 5b\n" |
559 | 534 |
560 // Check sa_flags: | 535 // Check sa_flags: |
561 // - We can ignore SA_NOCLDSTOP, SA_NOCLDWAIT, and SA_RESTART as they | 536 // - We can ignore SA_NOCLDSTOP, SA_NOCLDWAIT, and SA_RESTART as they |
562 // do not have any effect for SIGSEGV. | 537 // do not have any effect for SIGSEGV. |
563 // - We have to always register our signal handler with SA_NODEFER so | 538 // - We have to always register our signal handler with SA_NODEFER so |
564 // that the user's signal handler can make system calls which might | 539 // that the user's signal handler can make system calls which might |
565 // require additional help from our SEGV handler. | 540 // require additional help from our SEGV handler. |
566 // - If the user's signal handler wasn't supposed to be SA_NODEFER, then | 541 // - If the user's signal handler wasn't supposed to be SA_NODEFER, then |
567 // we emulate this behavior by keeping track of a recursion counter. | 542 // we emulate this behavior by keeping track of a recursion counter. |
568 // | 543 // |
569 // TODO(markus): If/when we add support for sigaltstack(), we have to | 544 // TODO(markus): If/when we add support for sigaltstack(), we have to |
570 // handle SA_ONSTACK. | 545 // handle SA_ONSTACK. |
571 "24:cmpl $0, %%fs:0x1040-0x58\n"// check if we failed inside of SEGV handler | 546 "22:cmpl $0, %%fs:0x1040-0x58\n"// check if we failed inside of SEGV handler |
572 "jnz 23b\n" // if so, then terminate program | 547 "jnz 21b\n" // if so, then terminate program |
573 "mov 0(%%eax), %%ebx\n" // sa_segv_.sa_sigaction | 548 "mov 0(%%eax), %%ebx\n" // sa_segv_.sa_sigaction |
574 "mov 4(%%eax), %%ecx\n" // sa_segv_.sa_flags | 549 "mov 4(%%eax), %%ecx\n" // sa_segv_.sa_flags |
575 "btl $31, %%ecx\n" // SA_RESETHAND | 550 "btl $31, %%ecx\n" // SA_RESETHAND |
576 "jnc 25f\n" | 551 "jnc 23f\n" |
577 "movl $0, 0(%%eax)\n" // set handler to SIG_DFL | 552 "movl $0, 0(%%eax)\n" // set handler to SIG_DFL |
578 "25:btl $30, %%ecx\n" // SA_NODEFER | 553 "23:btl $30, %%ecx\n" // SA_NODEFER |
579 "jc 28f\n" | 554 "jc 26f\n" |
580 "btl $2, %%ecx\n" // SA_SIGINFO | 555 "btl $2, %%ecx\n" // SA_SIGINFO |
581 "jnc 26f\n" | 556 "jnc 24f\n" |
582 "mov %%edi, 0(%%esp)\n" // trigger a SEGV on return | 557 "movl $27f, 0(%%esp)\n" // trigger a SEGV on return (if NX enabled) |
Mark Seaborn
2010/11/09 09:40:31
I don't understand the "(if NX enabled)" comment.
| |
583 "incl %%fs:0x1040-0x58\n" // increment recursion counter | 558 "incl %%fs:0x1040-0x58\n" // increment recursion counter |
584 "jmp *%%ebx\n" // call user's signal handler | 559 "jmp *%%ebx\n" // call user's signal handler |
585 "26:mov %%esi, 0(%%esp)\n" | 560 "24:movl $28f, 0(%%esp)\n" |
586 "incl %%fs:0x1040-0x58\n" // increment recursion counter | 561 "incl %%fs:0x1040-0x58\n" // increment recursion counter |
587 | 562 |
588 // We always register the signal handler to give us rt-style signal | 563 // We always register the signal handler to give us rt-style signal |
589 // frames. But if the user asked for legacy signal frames, we must | 564 // frames. But if the user asked for legacy signal frames, we must |
590 // convert the signal frame prior to calling the user's signal handler. | 565 // convert the signal frame prior to calling the user's signal handler. |
591 "27:sub $0x1C8, %%esp\n" // a legacy signal stack is much larger | 566 "25:sub $0x1C8, %%esp\n" // a legacy signal stack is much larger |
592 "mov 0x1CC(%%esp), %%eax\n" // push signal number | 567 "mov 0x1CC(%%esp), %%eax\n" // push signal number |
593 "push %%eax\n" | 568 "push %%eax\n" |
594 "mov 0x1CC(%%esp), %%eax\n" // push restorer function | 569 "mov 0x1CC(%%esp), %%eax\n" // push restorer function |
595 "push %%eax\n" | 570 "push %%eax\n" |
596 "lea 0x274(%%esp), %%esi\n" // copy siginfo register values | 571 "lea 0x274(%%esp), %%esi\n" // copy siginfo register values |
597 "lea 0x8(%%esp), %%edi\n" // into new location | 572 "lea 0x8(%%esp), %%edi\n" // into new location |
598 "mov $22, %%ecx\n" | 573 "mov $22, %%ecx\n" |
599 "cld\n" | 574 "cld\n" |
600 "rep movsl\n" | 575 "rep movsl\n" |
601 "mov 0x2CC(%%esp), %%eax\n" // copy first half of signal mask | 576 "mov 0x2CC(%%esp), %%eax\n" // copy first half of signal mask |
602 "mov %%eax, 0x58(%%esp)\n" | 577 "mov %%eax, 0x58(%%esp)\n" |
603 "lea 31f, %%esi\n" | |
604 "lea 0x2D4(%%esp), %%edi\n" // patch up retcode magic numbers | |
605 "movb $2, %%cl\n" | |
606 "rep movsl\n" | |
607 "jmp *%%ebx\n" // call user's signal handler | 578 "jmp *%%ebx\n" // call user's signal handler |
608 "28:lea 6b, %%eax\n" // set appropriate restorer function | 579 "26:movl $7b, 0(%%esp)\n" // set appropriate restorer function |
609 "mov %%eax, 0(%%esp)\n" | |
610 "btl $2, %%ecx\n" // SA_SIGINFO | 580 "btl $2, %%ecx\n" // SA_SIGINFO |
611 "jnc 27b\n" | 581 "jnc 25b\n" |
612 "lea 29f, %%eax\n" | 582 "movl $6b, 0(%%esp)\n" // set appropriate restorer function |
Mark Seaborn
2010/11/09 09:40:31
Indentation is 1 space off
| |
613 "mov %%eax, 0(%%esp)\n" // set appropriate restorer function | |
614 "jmp *%%ebx\n" // call user's signal handler | 583 "jmp *%%ebx\n" // call user's signal handler |
615 "29:pushl $30f\n" // emulate rt_sigreturn() | 584 "27:decl %%fs:0x1040-0x58\n" |
616 "jmp 5b\n" | 585 "jmp 6b\n" |
617 | 586 "28:decl %%fs:0x1040-0x58\n" |
618 // Non-executable versions of the restorer function. We use these to | 587 "jmp 7b\n" |
619 // trigger a SEGV upon returning from the user's signal handler, giving | |
620 // us an ability to clean up prior to returning from the SEGV handler. | |
621 ".pushsection .data\n" // move code into non-executable section | |
622 "30:mov $173, %%eax\n" // NR_rt_sigreturn | |
623 "int $0x80\n" // gdb looks for this signature when doing | |
624 ".byte 0\n" // backtraces | |
625 "31:pop %%eax\n" | |
626 "mov $119, %%eax\n" // NR_sigreturn | |
627 "int $0x80\n" | |
628 ".popsection\n" | |
629 #else | 588 #else |
630 #error Unsupported target platform | 589 #error Unsupported target platform |
631 #endif | 590 #endif |
632 ".pushsection \".rodata\"\n" | 591 ".pushsection \".rodata\"\n" |
633 #ifndef NDEBUG | 592 #ifndef NDEBUG |
634 "100:.asciz \"RDTSC(P): Executing handler\\n\"\n" | 593 "100:.asciz \"RDTSC(P): Executing handler\\n\"\n" |
635 "200:.asciz \"INT $0x0: Executing handler\\n\"\n" | 594 "200:.asciz \"INT $0x0: Executing handler\\n\"\n" |
636 #endif | 595 #endif |
637 ".popsection\n" | 596 ".popsection\n" |
638 "999:pop %0\n" | 597 "999:pop %0\n" |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
874 } entrypoint; | 833 } entrypoint; |
875 *entrypoint.get_syscall_entrypoint() = syscallEntryPointNoFrame; | 834 *entrypoint.get_syscall_entrypoint() = syscallEntryPointNoFrame; |
876 | 835 |
877 // We can no longer check for sandboxing support at this point, but we also | 836 // We can no longer check for sandboxing support at this point, but we also |
878 // know for a fact that it is available (as we just turned it on). So update | 837 // know for a fact that it is available (as we just turned it on). So update |
879 // the status to reflect this information. | 838 // the status to reflect this information. |
880 status_ = STATUS_ENABLED; | 839 status_ = STATUS_ENABLED; |
881 } | 840 } |
882 | 841 |
883 } // namespace | 842 } // namespace |
OLD | NEW |