Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Darwin] Fix symbolization for recent simulator runtimes.
Summary: Due to sandbox restrictions in the recent versions of the simulator runtime the atos program is no longer able to access the task port of a parent process without additional help. This patch fixes this by registering a task port for the parent process before spawning atos and also tells atos to look for this by setting a special environment variable. This patch is based on an Apple internal fix (rdar://problem/43693565) that unfortunately contained a bug (rdar://problem/58789439) because it used setenv() to set the special environment variable. This is not safe because in certain circumstances this can trigger a call to realloc() which can fail during symbolization leading to deadlock. A test case is included that captures this problem. The approach used to set the necessary environment variable is as follows: 1. Calling `putenv()` early during process init (but late enough that malloc/realloc works) to set a dummy value for the environment variable. 2. Just before `atos` is spawned the storage for the environment variable is modified to contain the correct PID. A flaw with this approach is that if the application messes with the atos environment variable (i.e. unsets it or changes it) between the time its set and the time we need it then symbolization will fail. We will ignore this issue for now but a `DCHECK()` is included in the patch that documents this assumption but doesn't check it at runtime to avoid calling `getenv()`. The issue reported in rdar://problem/58789439 manifested as a deadlock during symbolization in the following situation: 1. Before TSan detects an issue something outside of the runtime calls setenv() that sets a new environment variable that wasn't previously set. This triggers a call to malloc() to allocate a new environment array. This uses TSan's normal user-facing allocator. LibC stores this pointer for future use later. 2. TSan detects an issue and tries to launch the symbolizer. When we are in the symbolizer we switch to a different (internal allocator) and then we call setenv() to set a new environment variable. When this happen setenv() sees that it needs to make the environment array larger and calls realloc() on the existing enviroment array because it remembers that it previously allocated memory for it. Calling realloc() fails here because it is being called on a pointer its never seen before. The included test case closely reproduces the originally reported problem but it doesn't replicate the `((kBlockMagic)) == ((((u64*)addr)[0])` assertion failure exactly. This is due to the way TSan's normal allocator allocates the environment array the first time it is allocated. In the test program addr[0] accesses an inaccessible page and raises SIGBUS. If TSan's SIGBUS signal handler is active, the signal is caught and symbolication is attempted again which results in deadlock. In the originally reported problem the pointer is successfully derefenced but then the assert fails due to the provided pointer not coming from the active allocator. When the assert fails TSan tries to symbolicate the stacktrace while already being in the middle of symbolication which results in deadlock. rdar://problem/58789439 Reviewers: kubamracek, yln Subscribers: jfb, #sanitizers, llvm-commits Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D78179
- Loading branch information