Linux early injection: program break should follow the executable, not dynamorio
From rnk@google.com on December 04, 2012 15:52:19
When DynamoRIO allocates reachable memory, it often follows DR's own image, causing further calls to brk() to fail. Dynamically linked apps can handle a brk() call failure by falling back to mmap, but statically linked apps (where we have to use early injection) crash while attempting to set errno.
The crash looks like it might be a bug in glibc. The original glibc source code does: int __brk (void _addr) { void *newbrk; __curbrk = newbrk = (void *) INLINE_SYSCALL (brk, 1, addr); if (newbrk < addr) { _set_errno (ENOMEM); / CRASH */ return -1; } return 0; }
Which generates this code to set errno: 0x0000000000465678 <+40>: mov $0xffffffffffffffc0,%rax 0x000000000046567f <+47>: movl $0xc,%fs:(%rax) 0x0000000000465686 <+54>: mov $0xffffffff,%eax 0x000000000046568b <+59>: retq
Which we faithfully mangle like this: 0x0000000071dd9fa8 48 c7 c0 c0 ff ff ff mov $0xffffffc0 -> %rax 0x0000000071dd9faf 65 48 89 0c 25 10 00 mov %rcx -> %gs:0x10 00 00 0x0000000071dd9fb8 65 48 8b 0c 25 80 00 mov %gs:0x00000080 -> %rcx 00 00 0x0000000071dd9fc1 c7 04 08 0c 00 00 00 mov $0x0000000c -> (%rax,%rcx,1) 0x0000000071dd9fc8 65 48 8b 0c 25 10 00 mov %gs:0x10 -> %rcx 00 00 0x0000000071dd9fd1 b8 ff ff ff ff mov $0xffffffff -> %eax 0x0000000071dd9fd6 65 48 89 0c 25 10 00 mov %rcx -> %gs:0x10 00 00 0x0000000071dd9fdf 59 pop %rsp (%rsp) -> %rcx %rsp 0x0000000071dd9fe0 e9 db 94 ff ff jmp $0x0000000071dd34c0 <shared_bb_ibl_ret>
We may be able to just call SYS_brk to change the program break after we map it, but it's possible it won't accept just any absolute address.
Original issue: http://code.google.com/p/dynamorio/issues/detail?id=1004