Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // mach_override.c semver:1.2.0 | 1 // mach_override.c semver:1.2.0 |
| 2 // Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com | 2 // Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com |
| 3 // Some rights reserved: http://opensource.org/licenses/mit | 3 // Some rights reserved: http://opensource.org/licenses/mit |
| 4 // https://github.com/rentzsch/mach_override | 4 // https://github.com/rentzsch/mach_override |
| 5 | 5 |
| 6 #include "mach_override.h" | 6 #include "mach_override.h" |
| 7 #if defined(__i386__) || defined(__x86_64__) | 7 #if defined(__i386__) || defined(__x86_64__) |
| 8 #include "udis86.h" | 8 #include "udis86.h" |
| 9 #endif | 9 #endif |
| 10 | 10 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 0x8001FFFC, // lwz r0,-4(SP) | 34 0x8001FFFC, // lwz r0,-4(SP) |
| 35 0x60000000, // nop ; optionally replaced | 35 0x60000000, // nop ; optionally replaced |
| 36 0x4E800420 // bctr | 36 0x4E800420 // bctr |
| 37 }; | 37 }; |
| 38 | 38 |
| 39 #define kAddressHi 3 | 39 #define kAddressHi 3 |
| 40 #define kAddressLo 5 | 40 #define kAddressLo 5 |
| 41 #define kInstructionHi 10 | 41 #define kInstructionHi 10 |
| 42 #define kInstructionLo 11 | 42 #define kInstructionLo 11 |
| 43 | 43 |
| 44 #elif defined(__i386__) | 44 #elif defined(__i386__) |
| 45 | 45 |
| 46 #define kOriginalInstructionsSize 16 | 46 #define kOriginalInstructionsSize 16 |
| 47 | 47 |
| 48 char kIslandTemplate[] = { | 48 char kIslandTemplate[] = { |
| 49 // kOriginalInstructionsSize nop instructions so that we | 49 // kOriginalInstructionsSize nop instructions so that we |
| 50 // should have enough space to host original instructions | 50 // should have enough space to host original instructions |
| 51 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, | 51 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, |
| 52 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, | 52 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, |
| 53 // Now the real jump instruction | 53 // Now the real jump instruction |
| 54 0xE9, 0xEF, 0xBE, 0xAD, 0xDE | 54 0xE9, 0xEF, 0xBE, 0xAD, 0xDE |
| 55 }; | 55 }; |
| 56 | 56 |
| 57 #define kInstructions 0 | 57 #define kInstructions 0 |
| 58 #define kJumpAddress kInstructions + kOriginalInstructionsSize + 1 | 58 #define kJumpAddress kInstructions + kOriginalInstructionsSize + 1 |
| 59 #elif defined(__x86_64__) | 59 #elif defined(__x86_64__) |
| 60 | 60 |
| 61 #define kOriginalInstructionsSize 32 | 61 #define kOriginalInstructionsSize 32 |
| 62 | 62 |
| 63 #define kJumpAddress kOriginalInstructionsSize + 6 | 63 #define kJumpAddress kOriginalInstructionsSize + 6 |
| 64 #define kMaxJumpOffset (0x7fffffffUL) | |
| 64 | 65 |
| 65 char kIslandTemplate[] = { | 66 char kIslandTemplate[] = { |
| 66 // kOriginalInstructionsSize nop instructions so that we | 67 // kOriginalInstructionsSize nop instructions so that we |
| 67 // should have enough space to host original instructions | 68 // should have enough space to host original instructions |
| 68 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, | 69 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, |
| 69 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, | 70 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, |
| 70 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, | 71 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, |
| 71 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, | 72 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, |
| 72 // Now the real jump instruction | 73 // Now the real jump instruction |
| 73 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, | 74 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 260 if( !err ) | 261 if( !err ) |
| 261 err = setBranchIslandTarget_i386( escapeIsland, overrideFunction Address, 0 ); | 262 err = setBranchIslandTarget_i386( escapeIsland, overrideFunction Address, 0 ); |
| 262 | 263 |
| 263 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); | 264 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); |
| 264 // Build the jump relative instruction to the escape island | 265 // Build the jump relative instruction to the escape island |
| 265 #endif | 266 #endif |
| 266 | 267 |
| 267 | 268 |
| 268 #if defined(__i386__) || defined(__x86_64__) | 269 #if defined(__i386__) || defined(__x86_64__) |
| 269 if (!err) { | 270 if (!err) { |
| 270 » » uint32_t addressOffset = ((char*)escapeIsland - (char*)originalF unctionPtr - 5); | 271 » » // TODO: On 64-bit, move to opcode FF/4 (jmp 64-bit absolute) in stead of |
|
Robert Sesek
2017/06/20 20:54:15
I looked at this and I think the main concern woul
Mark Mentovai
2017/06/20 21:08:53
Robert Sesek wrote:
Boris Vidolov
2017/06/21 00:02:21
@rsesek:
Indeed, overriding more bytes is what I a
| |
| 272 » » // E9 (jmp 32-bit relative to RIP). Then we should update the | |
|
Mark Mentovai
2017/06/20 20:32:34
You don’t need “the” at the end of the line.
Boris Vidolov
2017/06/21 00:02:21
Done.
| |
| 273 » » // allocateBranchIsland to simply allocate any page in the addre ss space. | |
| 274 » » // See the 64-bit version of kIslandTemplate array. | |
| 275 » » int64_t addressOffset64 = ((char*)escapeIsland - (char*)original FunctionPtr - 5); | |
| 276 » » int32_t addressOffset = ((char*)escapeIsland - (char*)originalFu nctionPtr - 5); | |
| 277 » » assert(addressOffset64 == addressOffset); | |
| 271 addressOffset = OSSwapInt32(addressOffset); | 278 addressOffset = OSSwapInt32(addressOffset); |
| 272 | 279 |
| 273 jumpRelativeInstruction |= 0xE900000000000000LL; | 280 jumpRelativeInstruction |= 0xE900000000000000LL; |
| 274 jumpRelativeInstruction |= ((uint64_t)addressOffset & 0xffffffff ) << 24; | 281 jumpRelativeInstruction |= ((uint64_t)addressOffset & 0xffffffff ) << 24; |
| 275 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction); | 282 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction); |
| 276 } | 283 } |
| 277 #endif | 284 #endif |
| 278 | 285 |
| 279 // Optionally allocate & return the reentry island. This may contai n relocated | 286 // Optionally allocate & return the reentry island. This may contai n relocated |
| 280 // jmp instructions and so has all the same addressing reachability req uirements | 287 // jmp instructions and so has all the same addressing reachability req uirements |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 378 | 385 |
| 379 ************************************************************************ ***/ | 386 ************************************************************************ ***/ |
| 380 | 387 |
| 381 mach_error_t | 388 mach_error_t |
| 382 allocateBranchIsland( | 389 allocateBranchIsland( |
| 383 BranchIsland **island, | 390 BranchIsland **island, |
| 384 int allocateHigh, | 391 int allocateHigh, |
| 385 void *originalFunctionAddress) | 392 void *originalFunctionAddress) |
| 386 { | 393 { |
| 387 assert( island ); | 394 assert( island ); |
| 388 » | 395 |
| 389 mach_error_t err = err_none; | 396 mach_error_t err = err_none; |
| 390 | 397 |
| 391 if( allocateHigh ) { | 398 if( allocateHigh ) { |
| 392 assert( sizeof( BranchIsland ) <= PAGE_SIZE ); | 399 assert( sizeof( BranchIsland ) <= PAGE_SIZE ); |
| 393 vm_address_t page = 0; | 400 vm_address_t page = 0; |
| 394 #if defined(__i386__) | 401 #if defined(__i386__) |
| 395 err = vm_allocate( mach_task_self(), &page, PAGE_SIZE, VM_FLAGS_ ANYWHERE ); | 402 err = vm_allocate( mach_task_self(), &page, PAGE_SIZE, VM_FLAGS_ ANYWHERE ); |
| 396 if( err == err_none ) | 403 if( err == err_none ) |
| 397 *island = (BranchIsland*) page; | 404 *island = (BranchIsland*) page; |
| 398 #else | 405 #else |
| 399 | 406 |
| 400 #if defined(__ppc__) || defined(__POWERPC__) | 407 #if defined(__ppc__) || defined(__POWERPC__) |
| 401 vm_address_t first = 0xfeffffff; | 408 vm_address_t first = 0xfeffffff; |
| 402 vm_address_t last = 0xfe000000 + PAGE_SIZE; | 409 vm_address_t last = 0xfe000000 + PAGE_SIZE; |
| 403 #elif defined(__x86_64__) | 410 #elif defined(__x86_64__) |
| 404 » » // 64-bit ASLR is in bits 13-28 | 411 » » // This logic is more complex due to the 32-bit limit of the jum p out |
| 405 » » vm_address_t first = ((uint64_t)originalFunctionAddress & ~( (0x FUL << 28) | (PAGE_SIZE - 1) ) ) | (0x1UL << 31); | 412 » » // of the original function. Once that limitation is removed, we can |
| 406 » » vm_address_t last = (uint64_t)originalFunctionAddress & ~((0x1UL << 32) - 1); | 413 » » // use vm_allocate with VM_FLAGS_ANYWHERE as in the i386 code ab ove. |
| 414 » » const uint64_t kPageMask = ~(PAGE_SIZE - 1); | |
| 415 » » vm_address_t first = (uint64_t)originalFunctionAddress - kMaxJum pOffset; | |
| 416 » » first = (first & kPageMask) + PAGE_SIZE; // Align up to the next page start | |
| 417 » » if (first > (uint64_t)originalFunctionAddress) first = 0; | |
| 418 » » vm_address_t last = (uint64_t)originalFunctionAddress + kMaxJump Offset; | |
| 419 » » if (last < (uint64_t)originalFunctionAddress) last = ULONG_MAX; | |
| 407 #endif | 420 #endif |
| 408 | 421 |
| 409 page = first; | 422 page = first; |
| 410 int allocated = 0; | 423 int allocated = 0; |
| 411 vm_map_t task_self = mach_task_self(); | 424 vm_map_t task_self = mach_task_self(); |
| 412 | 425 |
| 413 » » while( !err && !allocated && page != last ) { | 426 » » while( !err && !allocated && page < last ) { |
| 414 | 427 |
| 415 err = vm_allocate( task_self, &page, PAGE_SIZE, 0 ); | 428 err = vm_allocate( task_self, &page, PAGE_SIZE, 0 ); |
| 416 if( err == err_none ) | 429 if( err == err_none ) |
| 417 allocated = 1; | 430 allocated = 1; |
| 418 else if( err == KERN_NO_SPACE ) { | 431 else if( err == KERN_NO_SPACE ) { |
| 419 #if defined(__x86_64__) | 432 #if defined(__x86_64__) |
| 420 » » » » page -= PAGE_SIZE; | 433 » » » » // This memory region is not suitable, skip it: |
| 434 » » » » vm_address_t region_start = page; | |
| 435 » » » » vm_size_t region_size; | |
| 436 » » » » mach_msg_type_number_t int_count = VM_REGION_BAS IC_INFO_COUNT_64; | |
| 437 » » » » vm_region_basic_info_data_64_t vm_region_info; | |
| 438 » » » » mach_port_t object_name; | |
| 439 » » » » kern_return_t region_result = | |
|
Mark Mentovai
2017/06/20 20:32:34
You can just reuse err here. And you can reuse pag
Boris Vidolov
2017/06/21 00:02:21
Done. I needed to step through the code a lot, hen
| |
| 440 » » » » » » vm_region_64(task_self, ®ion_ start, ®ion_size, | |
| 441 » » » » » » » VM_REGION_BASIC_INFO_64, (vm_region_info_t)&vm_region_info, | |
| 442 » » » » » » » &int_count, &object_name ); | |
| 443 » » » » if (region_result == KERN_SUCCESS) { | |
| 444 » » » » » page = region_start + region_size; | |
| 445 » » » » } else { | |
| 446 » » » » » err = region_result; | |
| 447 » » » » » break; | |
| 448 » » » » } | |
| 421 #else | 449 #else |
| 422 page += PAGE_SIZE; | 450 page += PAGE_SIZE; |
| 423 #endif | 451 #endif |
| 424 err = err_none; | 452 err = err_none; |
| 425 } | 453 } |
| 426 } | 454 } |
| 427 if( allocated ) | 455 if( allocated ) |
| 428 *island = (BranchIsland*) page; | 456 *island = (BranchIsland*) page; |
| 429 else if( !allocated && !err ) | 457 else if( !allocated && !err ) |
| 430 err = KERN_NO_SPACE; | 458 err = KERN_NO_SPACE; |
| 431 #endif | 459 #endif |
| 432 } else { | 460 } else { |
| 433 void *block = malloc( sizeof( BranchIsland ) ); | 461 void *block = malloc( sizeof( BranchIsland ) ); |
| 434 if( block ) | 462 if( block ) |
| 435 *island = block; | 463 *island = block; |
| 436 else | 464 else |
| 437 err = KERN_NO_SPACE; | 465 err = KERN_NO_SPACE; |
| 438 } | 466 } |
| 439 if( !err ) | 467 if( !err ) |
| 440 (**island).allocatedHigh = allocateHigh; | 468 (**island).allocatedHigh = allocateHigh; |
| 441 » | 469 |
| 442 return err; | 470 return err; |
| 443 } | 471 } |
| 444 | 472 |
| 445 /******************************************************************************* | 473 /******************************************************************************* |
| 446 Implementation: Deallocates memory for a branch island. | 474 Implementation: Deallocates memory for a branch island. |
| 447 | 475 |
| 448 @param island -> The island to deallocate. | 476 @param island -> The island to deallocate. |
| 449 @result <- mach_error_t | 477 @result <- mach_error_t |
| 450 | 478 |
| 451 ************************************************************************ ***/ | 479 ************************************************************************ ***/ |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 691 ); | 719 ); |
| 692 #elif defined(__x86_64__) | 720 #elif defined(__x86_64__) |
| 693 void atomic_mov64( | 721 void atomic_mov64( |
| 694 uint64_t *targetAddress, | 722 uint64_t *targetAddress, |
| 695 uint64_t value ) | 723 uint64_t value ) |
| 696 { | 724 { |
| 697 *targetAddress = value; | 725 *targetAddress = value; |
| 698 } | 726 } |
| 699 #endif | 727 #endif |
| 700 #endif | 728 #endif |
| OLD | NEW |