This is an archive of the discontinued LLVM Phabricator instance.

[Sanitizer] Add interceptor for ptsname
AbandonedPublic

Authored by labath on Sep 30 2020, 5:21 AM.

Details

Summary

Works the same way as the ttyname interceptor.

Diff Detail

Event Timeline

labath created this revision.Sep 30 2020, 5:21 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 30 2020, 5:21 AM
labath requested review of this revision.Sep 30 2020, 5:21 AM
labath added inline comments.Sep 30 2020, 5:23 AM
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
4904

I'm not sure I understand the difference between COMMON_INTERCEPTOR_INITIALIZE_RANGE and COMMON_INTERCEPTOR_WRITE_RANGE. For example, I would have expected tsan to warn about concurrent usages of ptsname from different threads (and changing this to WRITE_RANGE does achieve that), but maybe there is a reason why these functions use the INITIALIZE macro (?)

labath abandoned this revision.Sep 30 2020, 5:26 AM

Abandoning in favor of D88547 (though I'd still be interested to know the answer to my inline question).

Abandoning in favor of D88547 (though I'd still be interested to know the answer to my inline question).

My understanding:

COMMON_INTERCEPTOR_INITIALIZE_RANGE is only defined for msan.

  • asan re-defines COMMON_INTERCEPTOR_WRITE_RANGE (the buffer is specified by the user - the addressability needs to be checked) but not COMMON_INTERCEPTOR_INITIALIZE_RANGE (static storage is known to be *addressable* so there is no need to check addressability).
  • tsan re-defines COMMON_INTERCEPTOR_WRITE_RANGE (the buffer is specified by the user - the potential data race needs to be checked) but not COMMON_INTERCEPTOR_INITIALIZE_RANGE (data race will not be checked - potential false negatives).

Consider a function that returns a pointer to a static buffer with the contents that are somehow initialized internally with proper synchronization. If the interceptor uses _WRITE, TSan will understand that as a data race because it can not see the internal synchronization. That why _INITIALIZE macro is used by MSan (the memory has somehow been initialized) but not by TSan (there may not have been a store there *right now*).

Another example is strerror which sometimes returns a pointer to static data (always initialized, does not require any sanitizer handling) and sometimes to a freshly allocated thread-local buffer.

Consider a function that returns a pointer to a static buffer with the contents that are somehow initialized internally with proper synchronization. If the interceptor uses _WRITE, TSan will understand that as a data race because it can not see the internal synchronization. That why _INITIALIZE macro is used by MSan (the memory has somehow been initialized) but not by TSan (there may not have been a store there *right now*).

Another example is strerror which sometimes returns a pointer to static data (always initialized, does not require any sanitizer handling) and sometimes to a freshly allocated thread-local buffer.

Interesting. Thanks for the explanation. So, we're preferring a false negative (not reporting a race in case the function doesn't do anything fancy -- a thing which is pretty hard to do in the ptsname case) over a false positive (reporting a race even if it does). Kind of makes sense. Not sure its the right trade-off for this function, but I don't want to revisit past design decisions.