DynamoRIO / DynamoRIO/dynamorio

ASSERT(iter->vm_start == executable_start) when a statically linked app has duplicate executable mappings

Open
#7,823 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
3.2k
Forks
629
Avg merge
2d 15h
Merged PRs (30d)
31

Description

**Describe the bug**
In workloads using symbolizers which create a duplicate mapping for the binary, dynamoRIO triggers the assert.

**To Reproduce**
Minimal example that triggers this assert by creating a duplicate `MAP_SHARED` mapping for `/proc/self/exe`.

```cpp
/*

BUILD INSTRUCTIONS:

DR=/path/to/DynamoRIO-Linux-11.x
g++ -o repro repro.cpp -I$DR/include -L$DR/lib64/debug -L$DR/lib64/ \
-ldynamorio_static -ldrlibc -ldl -lm -static \
-Wl,--defsym=dynamorio_so_start=__executable_start \
-Wl,--defsym=dynamorio_so_end=end
./repro

*/

#include
#include
#include
#include
#include
#include

extern "C" {
extern void dr_app_setup_and_start(void);
extern void dr_app_stop_and_cleanup(void);
extern int dr_app_running_under_dynamorio(void);
}

int main() {
char exe[4096];
ssize_t len = readlink("/proc/self/exe", exe, sizeof(exe) - 1);
assert(len > 0);
exe[len] = '\0';

int fd = open(exe, O_RDONLY);
assert(fd >= 0);

struct stat st{};
fstat(fd, &st);
void* m = mmap(nullptr, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
close(fd);
assert(m != MAP_FAILED);

dr_app_setup_and_start(); // <-- hits the assert
assert(dr_app_running_under_dynamorio());
dr_app_stop_and_cleanup();

munmap(m, st.st_size);
return 0;
}
```

Output:

```
./repro

vm_start == executable_start
(Error occurred @0 frags in tid 2619474)
version 11.91.20504, custom build
-stack_size 64K -signal_stack_size 64K -max_elide_jmp 0 -max_elide_call 0 -vmm_block_size 64K -initial_heap_unit_size 64K -initial_heap_nonpers_size 64K -initial_global_heap_unit_size 512K -max_heap_unit_size 4M -heap_commit_increment 64K -cache_commit_increment 64K -cache_bb_unit_init 64K -cache_bb_unit_max 64K -cache_b
0x0000ffffe119bff0 0x00000000004a8a0c
0x0000ffffe119c190 0x0000000000835380
0x0000ffffe119c3e0 0x000000000083579c
0x0000ffffe119c470 0x00000000005648c8
0x0000ffffe119c540 0x000000000041703c
0x0000ffffe119c5f0 0x0000000000416788
0x0000ffffe119ce20 0x000000000041b1c8
0x0000ffffe119ce30 0x000000000041b4c8
0x0000ffffe119ce50 0x0000000000400938
0x0000ffffe119ce70 0x00000000008714d4
0x0000ffffe119df20 0x00000000008718bc
0x0000ffffe119e030 0x00000000004006f0
/home/user/dynamorio-project/repro=0x0000000000400000>

```

The app exits cleanly if the assert is manually skipped:

```
export DYNAMORIO_OPTIONS="-ignore_assert_list /home/runner/work/dynamorio/dynamorio/core/unix/os.c:10307"
```

Please also answer these questions:
- What happens when you run without any client? This is running without a client.
- What happens when you run with debug build ("-debug" flag to drrun/drconfig/drinject)? Assert triggers only in the debug build.

Please provide a symbolized callstack of any crash or assert so we do not have to speculate or guess as to where it is occurring (see our [Linux gdb instructions](https://dynamorio.org/page_debugging.html#autotoc_md146) and [Windows windbg instructions](https://dynamorio.org/page_debugging.html#autotoc_md157) to see how to load DynamoRIO symbols for a callstack). Not sure if this is needed for the assert. Can provide if needed.

**Versions**
- What version of DynamoRIO are you using?
- Does the latest build from https://github.com/DynamoRIO/dynamorio/releases solve the problem?
- What operating system version are you running on? ("Windows 10" is *not* sufficient: give the release number.)
- Is your application 32-bit or 64-bit?

**Additional context**
Add any other context about the problem here.

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.