Chromium Code Reviews| 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 |