This is an archive of the discontinued LLVM Phabricator instance.

[TSan][Darwin] Avoid crashes due to interpreting non-zero shadow content as a pointer
ClosedPublic

Authored by yln on Sep 22 2021, 5:52 AM.

Details

Summary

We would like to use TLS to store the ThreadState object (or at least a
reference ot it), but on Darwin accessing TLS via __thread or manually
by using pthread_key_* is problematic, because there are several places
where interceptors are called when TLS is not accessible (early process
startup, thread cleanup, ...).

Previously, we used a "poor man's TLS" implementation, where we use the
shadow memory of the pointer returned by pthread_self() to store a
pointer to the ThreadState object.

The problem with that was that certain operations can populate shadow
bytes unbeknownst to TSan, and we later interpret these non-zero bytes
as the pointer to our ThreadState object and crash on when dereferencing
the pointer.

This patch changes the storage location of our reference to the
ThreadState object to "real" TLS. We make this work by artificially
keeping this reference alive in the pthread_key destructor by resetting
the key value with pthread_setspecific().

This change also fixes the issue were the ThreadState object is
re-allocated after DestroyThreadState() because intercepted functions
can still get called on the terminating thread after the
THREAD_TERMINATE event.

Radar-Id: rdar://problem/72010355

Diff Detail

Event Timeline

yln requested review of this revision.Sep 22 2021, 5:52 AM
yln created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptSep 22 2021, 5:52 AM
Herald added a subscriber: Restricted Project. · View Herald Transcript
yln retitled this revision from Avoid crashes due to interpreting non-zero shadow content as a pointer to [TSan][Darwin] Avoid crashes due to interpreting non-zero shadow content as a pointer.Sep 23 2021, 7:47 AM
yln edited the summary of this revision. (Show Details)
dvyukov accepted this revision.Sep 30 2021, 6:44 AM
dvyukov added inline comments.
compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp
49

s/64/SANITIZER_CACHE_LINE_SIZE/

298

Please rebase this on ade5023c54cffcbefe0557b5473d55b06e40809b or it will break the test again.

This revision is now accepted and ready to land.Sep 30 2021, 6:44 AM
yln updated this revision to Diff 376231.Sep 30 2021, 8:17 AM
yln marked 2 inline comments as done.
yln edited the summary of this revision. (Show Details)

Rebase and address review feedback.

yln added inline comments.Sep 30 2021, 8:21 AM
compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp
298

Yes and thank you for the quick review Dmitry! :)

Is there anything blocking this?
I need this for https://reviews.llvm.org/D112603
That changes start re-setting shadow periodically which wipes ThreadState* pointer currently stored in the shadow:
https://reviews.llvm.org/D112603#3146853
(the current runtime can do the same if flush_memory_ms/memory_limit_mb flags are enabled, but somehow nobody noticed that)
If ThreadState* is stored as pthread specific, then it should resolve the issue as well.

This revision was landed with ongoing or failed builds.Nov 30 2021, 2:49 PM
This revision was automatically updated to reflect the committed changes.