diff options
Diffstat (limited to 'results/classifier/zero-shot-user-mode/syscall/1886097')
| -rw-r--r-- | results/classifier/zero-shot-user-mode/syscall/1886097 | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/results/classifier/zero-shot-user-mode/syscall/1886097 b/results/classifier/zero-shot-user-mode/syscall/1886097 new file mode 100644 index 00000000..2fa678a1 --- /dev/null +++ b/results/classifier/zero-shot-user-mode/syscall/1886097 @@ -0,0 +1,39 @@ +syscall: 0.384 +instruction: 0.344 +runtime: 0.271 + + + +Error in user-mode calculation of ELF program's brk + +There's a discrepancy between the way QEMU user-mode and Linux calculate the initial program break for statically-linked binaries. I have a binary with the following segments: + + Program Headers: + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + EXIDX 0x065a14 0x00075a14 0x00075a14 0x00588 0x00588 R 0x4 + PHDR 0x0a3000 0x000a3000 0x000a3000 0x00160 0x00160 R 0x1000 + LOAD 0x0a3000 0x000a3000 0x000a3000 0x00160 0x00160 R 0x1000 + LOAD 0x000000 0x00010000 0x00010000 0x65fa0 0x65fa0 R E 0x10000 + LOAD 0x066b7c 0x00086b7c 0x00086b7c 0x02384 0x02384 RW 0x10000 + NOTE 0x000114 0x00010114 0x00010114 0x00044 0x00044 R 0x4 + TLS 0x066b7c 0x00086b7c 0x00086b7c 0x00010 0x00030 R 0x4 + GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x8 + GNU_RELRO 0x066b7c 0x00086b7c 0x00086b7c 0x00484 0x00484 R 0x1 + LOAD 0x07e000 0x00089000 0x00089000 0x03ff4 0x03ff4 R E 0x1000 + LOAD 0x098000 0x00030000 0x00030000 0x01000 0x01000 RW 0x1000 + +The call to set_brk in Linux's binfmt_elf.c receives these arguments: + + set_brk(0xa3160, 0xa3160, 1) + +Whereas in QEMU, info->brk gets set to 0x88f00. When the binary is run in QEMU, it crashes on the second call to brk, whereas it runs fine on real ARM hardware. I think the trouble is that the program break is set to an address lower than the virtual address of a LOAD segment (the program headers, in this case). + +I believe that this discrepancy arises because in QEMU, info->brk is only incremented when the LOAD segment in question has PROT_WRITE. For this binary, the LOAD segment with write permissions and the highest virtual address is + + LOAD 0x066b7c 0x00086b7c 0x00086b7c 0x02384 0x02384 RW 0x10000 + +which overlaps with the TLS segment: + + TLS 0x066b7c 0x00086b7c 0x00086b7c 0x00010 0x00030 R 0x4 + +However, the Linux kernel puts the program break after the loadable segment with the highest virtual address, regardless of flags. So I think the fix is for QEMU to do the same. \ No newline at end of file |