[asan/win] Use SRW locks to fix a race in BlockingMutex
authorReid Kleckner <rnk@google.com>
Mon, 30 Jul 2018 23:32:33 +0000 (23:32 +0000)
committerReid Kleckner <rnk@google.com>
Mon, 30 Jul 2018 23:32:33 +0000 (23:32 +0000)
commita5ed43c1c9c40b27a2f710781016bcac61f1d833
treea468d9cf5ccaaeec12c20d238ce03a14cbf94d44
parenta51403f5ccd81592e899360dd2d204d2e40a547c
[asan/win] Use SRW locks to fix a race in BlockingMutex

Summary:
Before my change, BlockingMutex used Windows critial sections. Critical
sections can only be initialized by calling InitializeCriticalSection,
dynamically.

The primary sanitizer allocator expects to be able to reinterpret zero
initialized memory as a BlockingMutex and immediately lock it.
RegionInfo contains a mutex, and it placement new is never called for
it. These objects are accessed via:
  RegionInfo *GetRegionInfo(uptr class_id) const {
    DCHECK_LT(class_id, kNumClasses);
    RegionInfo *regions = reinterpret_cast<RegionInfo *>(SpaceEnd());
    return &regions[class_id];
  }
The memory comes from the OS without any other initialization.

For various reasons described in the comments, BlockingMutex::Lock would
check if the object appeared to be zero-initialized, and it would lazily
call the LinkerInitialized constructor to initialize the critical
section. This pattern is obviously racy, and the code had a bunch of
FIXMEs about it.

The best fix here is to use slim reader writer locks, which can start
out zero-initialized. They are available starting in Windows Vista. I
think it's safe to go ahead and use them today.

Reviewers: kcc, vitalybuka

Subscribers: kubamracek, llvm-commits

Differential Revision: https://reviews.llvm.org/D49893

llvm-svn: 338331
compiler-rt/lib/sanitizer_common/sanitizer_mutex.h
compiler-rt/lib/sanitizer_common/sanitizer_win.cc