[PATCH] D77706: [Darwin] Fix symbolization for recent simulator runtimes.

Dan Liew via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 7 22:50:25 PDT 2020


delcypher created this revision.
delcypher added reviewers: kubamracek, yln.
Herald added subscribers: Sanitizers, jfb.
Herald added a project: Sanitizers.
delcypher added a parent revision: D77696: [Darwin] Teach `AtosSymbolizerProcess` to work on a copy of the environment..

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.

This patch takes a different approach by modifying a copy of the environment
that is passed to `atos` and so fixes both rdar://problem/43693565 and
rdar://problem/58789439.

In more detail calling `setenv()` during symbolization sometimes caused
a deadlock in the following situation:

1. Before TSan detects an issue Something 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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D77706

Files:
  compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp
  compiler-rt/test/tsan/Darwin/no_call_setenv_in_symbolize.cpp

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D77706.255900.patch
Type: text/x-patch
Size: 7270 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200408/ef9befcc/attachment.bin>


More information about the llvm-commits mailing list