DynamoRIO / DynamoRIO/dynamorio

CRASH, x86-64 cleancall save_fpstate causes incorrect passing of register operands

Open
#4,464 5 comments 0 reactions 0 assignees View on GitHub
Bug-ToolFail help wanted
Dominant language
C
Stars
3.2k
Forks
629
Avg merge
2d 15h
Merged PRs (30d)
31

Description

Passing `save_fpstate = true` to `dr_insert_clean_call` (or, alternatively, `DR_CLEANCALL_SAVE_FLOAT` to `dr_insert_clean_call_ex`) causes incorrect passing of register operands to the clean-call.

With `save_fpstate = false`:
```
+121 m4 @0x00007fbc087e71b8 48 8d a4 24 f8 f6 ff lea 0xfffff6f8(%rsp) -> %rsp
ff
+129 m4 @0x00007fbc087e3908 e8 5b 14 06 80 call $0x00007fbc8872dd00 %rsp -> %rsp 0xfffffff8(%rsp)[8byte]
+134 m4 @0x00007fbc087e5e18
+134 m4 @0x00007fbc087e2de0 48 8b 74 24 30 mov 0x30(%rsp)[8byte] -> %rsi
+139 m4 @0x00007fbc087e3c70 48 bf 37 64 68 cc bc mov $0x00007fbccc686437 -> %rdi
7f 00 00
+149 m4 @0x00007fbc087e5a18 e8 bb 62 fb 7f call $0x00007fbc88682b60 %rsp -> %rsp 0xfffffff8(%rsp)[8byte]
+154 m4 @0x00007fbc086d5aa8 e8 5b 15 06 80 call $0x00007fbc8872de00 %rsp -> %rsp 0xfffffff8(%rsp)[8byte]
```

With `save_fpstate = true`:
```
+121 m4 @0x00007fdaeb5571b8 48 8d a4 24 f8 f6 ff lea 0xfffff6f8(%rsp) -> %rsp
ff
+129 m4 @0x00007fdaeb553908 e8 5b 14 06 80 call $0x00007fdb6b49dd00 %rsp -> %rsp 0xfffffff8(%rsp)[8byte]
+134 m4 @0x00007fdaeb555e18 48 8d a4 24 00 fe ff lea 0xfffffe00(%rsp) -> %rsp
ff
+142 m4 @0x00007fdaeb553c70 48 0f ae 04 24 fxsave64 -> (%rsp)[512byte]
+147 m4 @0x00007fdaeb552de0 db e2 fnclex
+149 m4 @0x00007fdaeb555a18 9b fwait
+150 m4 @0x00007fdaeb445aa8 db e3 fninit
+152 m4 @0x00007fdaeb5554d8
+152 m4 @0x00007fdaeb557308 48 8b 74 24 30 mov 0x30(%rsp)[8byte] -> %rsi
+157 m4 @0x00007fdaeb4408b8 48 bf 37 64 3f af db mov $0x00007fdbaf3f6437 -> %rdi
7f 00 00
+167 m4 @0x00007fdaeb5584c0 e8 bb 62 fb 7f call $0x00007fdb6b3f2b60 %rsp -> %rsp 0xfffffff8(%rsp)[8byte]
+172 m4 @0x00007fdaeb443b28 48 0f ae 0c 24 fxrstor64 (%rsp)[512byte]
+177 m4 @0x00007fdaeb555b98 48 8d a4 24 00 02 00 lea 0x00000200(%rsp) -> %rsp
00
+185 m4 @0x00007fdaeb556738 e8 5b 15 06 80 call $0x00007fdb6b49de00 %rsp -> %rsp 0xfffffff8(%rsp)[8byte]
```
This is a two-parameter clean-call where the first parameter is an immediate and the second parameter is a register operand. You'll see that in both cases the second parameter is loaded from `0x30(%rsp)[8byte]`, but in the `save_fpstate = true` case this offset becomes incorrect due to the adjustment of the stack for the fxsave64 spill.

**To Reproduce**
Steps to reproduce the behavior:
1. Use `dr_insert_clean_call` with `save_fpstate = true` and an `opnd_t` which specifies a register operand.

Please also answer these questions:
- What happens when you run without any client? AFAICT, this is a bug in the implementation of a client API
- What happens when you run with debug build ("-debug" flag to drrun/drconfig/drinject)? Reproduces

**Versions**
- What version of DynamoRIO are you using? Fairly recent master
- What operating system version are you running on? Ubuntu 20.04.1 LTS
- Is your application 32-bit or 64-bit? 64-bit

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.