DynamoRIO / DynamoRIO/dynamorio

DR client spill slot not stable across clean call?

Open
#1,964 0 comments 0 reactions 0 assignees View on GitHub
Bug-AppCrash Component-API Hotlist-Release
Dominant language
C
Stars
3.2k
Forks
629
Avg merge
2d 15h
Merged PRs (30d)
31

Description

While testing #1954, I requested 2 TLS slots in drreg_init for
drcachesim's tracer, as it uses 2 scratch GPR regs. However, drreg always
keeps 1 for the flags, so the 2nd scratch reg is always in a DR slot in
this situation. I hit an app crash running the 2 drcachesim thread tests.
When the 2nd scratch reg is eax, _and_ it's in a DR slot (I tested in a
custom slot), we hit the app crash when it's lazily restored across a clean
call (in this case it was also lazily restored even later across an app
instr, but that's a separate issue: #1963).

The problem does not manifest right away: it's later. The clean call
writes data to a pipe and must somehow end up clobbering that TLS slot?
But how?

Note that this is not a drreg issue: this violate DR's contract that you
can pass args to a clean call in its TLS slots. DR only says you can't
rely on them being valid across app instrs.

```
interp: start_pc = 0xef1c54d9
0xef1c54d9 31 cf xor %ecx %edi -> %edi
wrote all 6 flags now!
0xef1c54db 81 cf ff fe fe fe or $0xfefefeff %edi -> %edi
0xef1c54e1 47 inc %edi -> %edi
0xef1c54e2 75 68 jnz $0xef1c554c
end_pc = 0xef1c54e4

instrument_basic_block ******************

before instrumentation:
TAG 0xef1c54d9
+0 L3 31 cf xor %ecx %edi -> %edi
+2 L3 81 cf ff fe fe fe or $0xfefefeff %edi -> %edi
+8 L3 47 inc %edi -> %edi
+9 L3 75 68 jnz $0xef1c554c
END 0xef1c54d9

drreg_event_bb_analysis @0.0xef1c54e2: eax=1 ecx=1 edx=1 ebx=1 esp=1 ebp=1 esi=1 edi=1 flags=287
drreg_event_bb_analysis @1.0xef1c54e1: eax=1 ecx=1 edx=1 ebx=1 esp=1 ebp=1 esi=1 edi=1 flags=1
drreg_event_bb_analysis @2.0xef1c54db: eax=1 ecx=1 edx=1 ebx=1 esp=1 ebp=1 esi=1 edi=1 flags=0
drreg_event_bb_analysis @3.0xef1c54d9: eax=1 ecx=1 edx=1 ebx=1 esp=1 ebp=1 esi=1 edi=1 flags=0
zzz 6780: picking any reg
drreg_reserve_reg_internal @0.0xef1c54e2: spilling ecx to slot 1
drreg_reserve_reg_internal @0.0xef1c54e2: spilling eax to slot 2
CLEANCALL: insert clean call to 0xf77bb379
CLEANCALL: bailout 0xf77bb379
insert_parameter_preparation: 0 args, 0 in-reg, 0 pre-push, 0/0 stack
drreg_unreserve_register @0.0xef1c54e2 ecx
drreg_unreserve_register @0.0xef1c54e2 eax
drreg_event_bb_insert_late @0.0xef1c54e2: lazily restoring eax
drreg_restore_reg_now @0.0xef1c54e2: restoring eax
drreg_event_bb_insert_late @0.0xef1c54e2: lazily restoring ecx
drreg_restore_reg_now @0.0xef1c54e2: restoring ecx

after instrumentation:
TAG 0xef1c54d9
+0 L3 31 cf xor %ecx %edi -> %edi
+2 L3 81 cf ff fe fe fe or $0xfefefeff %edi -> %edi
+8 L3 47 inc %edi -> %edi
+9 m4 @0xef87122c 64 89 0d 50 00 00 00 mov %ecx -> %fs:0x00000050[4byte]
+16 m4 @0xef87ac38 64 a3 0c 00 00 00 mov %eax -> %fs:0x0c[4byte]
+22 m4 @0xef87ca20 64 8b 0d 54 00 00 00 mov %fs:0x00000054[4byte] -> %ecx
+29 m4 @0xef873514 c7 01 0a 00 02 00 mov $0x0002000a -> (%ecx)[4byte]
+35 m4 @0xef92ae70 c7 41 04 d9 54 1c ef mov $0xef1c54d9 -> 0x04(%ecx)[4byte]
+42 m4 @0xef877010 c7 41 08 0b 00 02 00 mov $0x0002000b -> 0x08(%ecx)[4byte]
+49 m4 @0xef87da9c c7 41 0c 06 01 87 ef mov $0xef870106 -> 0x0c(%ecx)[4byte]
+56 m4 @0xef877050 c7 41 10 0a 00 02 00 mov $0x0002000a -> 0x10(%ecx)[4byte]
+63 m4 @0xef92ae30 c7 41 14 e2 54 1c ef mov $0xef1c54e2 -> 0x14(%ecx)[4byte]
+70 m4 @0xef834624
+70 m4 @0xef92b5c4 8d 49 18 lea 0x18(%ecx) -> %ecx
+73 m4 @0xef929f20 64 89 0d 54 00 00 00 mov %ecx -> %fs:0x00000054[4byte]
+80 m4 @0xef8731dc 8b 09 mov (%ecx)[4byte] -> %ecx
+82 m4 @0xef834344 e3 fe jecxz @0xef8789e8[4byte] %ecx
+84 m4 @0xef833b90 64 a3 00 00 00 00 mov %eax -> %fs:0x00[4byte]
+90 m4 @0xef87da5c 64 a1 10 00 00 00 mov %fs:0x10[4byte] -> %eax
+96 m4 @0xef879ee8 89 60 0c mov %esp -> 0x0c(%eax)[4byte]
+99 m4 @0xef8340fc 8b a0 68 01 00 00 mov 0x00000168(%eax)[4byte] -> %esp
+105 m4 @0xef835fb8 64 a1 00 00 00 00 mov %fs:0x00[4byte] -> %eax
+111 m4 @0xef928f30 8d a4 24 bc fe ff ff lea 0xfffffebc(%esp) -> %esp
+118 m4 @0xef831bc4 e8 67 be fb ff call $0xef7eaa40 %esp -> %esp 0xfffffffc(%esp)[4byte]
+123 m4 @0xef92cc38
+123 m4 @0xef928250 e8 a0 c7 f8 07 call $0xf77bb379 %esp -> %esp 0xfffffffc(%esp)[4byte]
+128 m4 @0xef928204 e8 e7 be fb ff call $0xef7eaac0 %esp -> %esp 0xfffffffc(%esp)[4byte]
+133 m4 @0xef927d54 64 a3 00 00 00 00 mov %eax -> %fs:0x00[4byte]
+139 m4 @0xef874008 64 a1 10 00 00 00 mov %fs:0x10[4byte] -> %eax
+145 m4 @0xef8792a8 8b 60 0c mov 0x0c(%eax)[4byte] -> %esp
+148 m4 @0xef87ae34 64 a1 00 00 00 00 mov %fs:0x00[4byte] -> %eax
+154 m4 @0xef8789e8
+154 m4 @0xef87529c 64 a1 0c 00 00 00 mov %fs:0x0c[4byte] -> %eax
+160 m4 @0xef92e1c4 64 8b 0d 50 00 00 00 mov %fs:0x00000050[4byte] -> %ecx
+167 L3 75 68 jnz $0xef1c554c
END 0xef1c54d9

clean_call_save:
0xef7eaa40 8d a4 24 48 01 00 00 lea 0x00000148(%esp) -> %esp
0xef7eaa47 8d a4 24 e8 fe ff ff lea 0xfffffee8(%esp) -> %esp
0xef7eaa4e c5 fd 7f 44 24 18 vmovdqa %ymm0 -> 0x18(%esp)[32byte]
0xef7eaa54 c5 fd 7f 4c 24 38 vmovdqa %ymm1 -> 0x38(%esp)[32byte]
0xef7eaa5a c5 fd 7f 54 24 58 vmovdqa %ymm2 -> 0x58(%esp)[32byte]
0xef7eaa60 c5 fd 7f 5c 24 78 vmovdqa %ymm3 -> 0x78(%esp)[32byte]
0xef7eaa66 c5 fd 7f a4 24 98 00 vmovdqa %ymm4 -> 0x00000098(%esp)[32byte]
00 00
0xef7eaa6f c5 fd 7f ac 24 b8 00 vmovdqa %ymm5 -> 0x000000b8(%esp)[32byte]
00 00
0xef7eaa78 c5 fd 7f b4 24 d8 00 vmovdqa %ymm6 -> 0x000000d8(%esp)[32byte]
00 00
0xef7eaa81 c5 fd 7f bc 24 f8 00 vmovdqa %ymm7 -> 0x000000f8(%esp)[32byte]
00 00
0xef7eaa8a 68 00 00 00 00 push $0x00000000 %esp -> %esp 0xfffffffc(%esp)[4byte]
0xef7eaa8f 9c pushf %esp -> %esp 0xfffffffc(%esp)[4byte]
0xef7eaa90 60 pusha %esp %eax %ebx %ecx %edx %ebp %esi %edi -> %esp 0xffffffe0(%esp)[32byte]
0xef7eaa91 fc cld
0xef7eaa92 8d 64 24 f8 lea 0xfffffff8(%esp) -> %esp
0xef7eaa96 c2 04 00 ret

clean_call_restore:
0xef7eaac0 8d 64 24 04 lea 0x04(%esp) -> %esp
0xef7eaac4 61 popa %esp (%esp)[32byte] -> %esp %eax %ebx %ecx %edx %ebp %esi %edi
0xef7eaac5 9d popf %esp (%esp)[4byte] -> %esp
0xef7eaac6 c5 fd 6f 44 24 1c vmovdqa 0x1c(%esp)[32byte] -> %ymm0
0xef7eaacc c5 fd 6f 4c 24 3c vmovdqa 0x3c(%esp)[32byte] -> %ymm1
0xef7eaad2 c5 fd 6f 54 24 5c vmovdqa 0x5c(%esp)[32byte] -> %ymm2
0xef7eaad8 c5 fd 6f 5c 24 7c vmovdqa 0x7c(%esp)[32byte] -> %ymm3
0xef7eaade c5 fd 6f a4 24 9c 00 vmovdqa 0x0000009c(%esp)[32byte] -> %ymm4
00 00
0xef7eaae7 c5 fd 6f ac 24 bc 00 vmovdqa 0x000000bc(%esp)[32byte] -> %ymm5
00 00
0xef7eaaf0 c5 fd 6f b4 24 dc 00 vmovdqa 0x000000dc(%esp)[32byte] -> %ymm6
00 00
0xef7eaaf9 c5 fd 6f bc 24 fc 00 vmovdqa 0x000000fc(%esp)[32byte] -> %ymm7
00 00
0xef7eab02 8d a4 24 1c 01 00 00 lea 0x0000011c(%esp) -> %esp
0xef7eab09 8d a4 24 bc fe ff ff lea 0xfffffebc(%esp) -> %esp
0xef7eab10 c2 40 01 ret $0x00000140 %esp (%esp)[4byte] -> %esp
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.