Skip to content

[rtsan] Make sure rtsan gets initialized on mac #100188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 11, 2024

Conversation

cjappl
Copy link
Contributor

@cjappl cjappl commented Jul 23, 2024

Intermittently on my mac I was getting the same nullptr crash in dlsym.

We need to make sure rtsan gets initialized on mac between when the binary starts running, and the first intercepted function is called. Until that point we should use the DlsymAllocator.

@cjappl
Copy link
Contributor Author

cjappl commented Jul 23, 2024

CC For review @vitalybuka @MaskRay @davidtrevelyan

@llvmbot
Copy link
Member

llvmbot commented Jul 23, 2024

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Chris Apple (cjappl)

Changes

Intermittently on my mac I was getting the same nullptr crash in dlsym.

We need to make sure rtsan gets initialized on mac between when the binary starts running, and the first intercepted function is called. Until that point we should use the DlsymAllocator.


Full diff: https://github.com/llvm/llvm-project/pull/100188.diff

1 Files Affected:

  • (modified) compiler-rt/lib/rtsan/rtsan_interceptors.cpp (+3-1)
diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors.cpp
index 4d5423ec629d2..833062c3de41e 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors.cpp
@@ -39,7 +39,6 @@
 
 using namespace __sanitizer;
 
-using __rtsan::rtsan_init_is_running;
 using __rtsan::rtsan_initialized;
 
 namespace {
@@ -49,6 +48,9 @@ struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
 } // namespace
 
 void ExpectNotRealtime(const char *intercepted_function_name) {
+  if (!rtsan_initialized)
+    __rtsan_init();
+
   __rtsan::GetContextForThisThread().ExpectNotRealtime(
       intercepted_function_name);
 }

@cjappl
Copy link
Contributor Author

cjappl commented Jul 30, 2024

Pinging reviewers @MaskRay @vitalybuka

Thanks as always for the help.

@vitalybuka vitalybuka requested review from MaskRay and vitalybuka July 30, 2024 17:31
@cjappl cjappl force-pushed the FixNonInitializationMac branch from 06321b5 to 0182c5d Compare July 30, 2024 19:15
@cjappl cjappl requested a review from vitalybuka July 30, 2024 19:15
@cjappl
Copy link
Contributor Author

cjappl commented Aug 7, 2024

Weekly ping of reviewers: @vitalybuka @MaskRay

Current state: All outstanding review comments have been addressed.

CHECK(!rtsan_init_is_running);
if (rtsan_initialized)
CHECK(!IsInitRunning());
if (__rtsan_is_initialized())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why don't you call a static one here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a benefit of calling a static function vs the external API function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(for the record, the external method must exist because we use it in rtsan_interceptors to see if we need to use the start-up allocator before dlsym is fully settled)


extern "C" {

SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_init() {
CHECK(!rtsan_init_is_running);
if (rtsan_initialized)
CHECK(!IsInitRunning());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it's cleaner with a mutex, like asan_inited_mutex

There is possibility that 2 racing thread will pass CHECK(!IsInitRunning());

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Alright, this now does the following:

Checks if initialized - using an atomic to prevent data races
If not, grabs the mutex
Once the mutex is grabbed, checks the atomic once more to ensure we don't double initialize.

I think this handles all the possible data races in this path.

The separation of rtsan_ensure_inited vs rtsan_init is to make sure the preinit array initialization of rtsan is as lean as possible. This is following some of the patterns I saw in other sanitizers.

@cjappl cjappl requested a review from vitalybuka August 8, 2024 13:30
@cjappl cjappl force-pushed the FixNonInitializationMac branch from d6982cc to d87f7db Compare August 11, 2024 20:56
@cjappl
Copy link
Contributor Author

cjappl commented Aug 11, 2024

Two very small updates since last review:

  1. Matching llvm style "If you use a braced initializer list when initializing a variable, use an equals before the open curly brace:"
- static atomic_uint8_t rtsan_initialized{0};
+ static atomic_uint8_t rtsan_initialized = {0};
  1. Got rid of the now-unused IsInitialized in favor of the __rtsan_is_initialized method, this was cruft from an earlier version of this review.

These two changes may be reviewed in the latest two commits, if anyone wants to see them in isolation.

I also rebased on latest main. I will likely merge this early next week

@vitalybuka vitalybuka merged commit 0a2a319 into llvm:main Aug 11, 2024
5 of 7 checks passed
@cjappl cjappl deleted the FixNonInitializationMac branch August 11, 2024 23:12
@cjappl
Copy link
Contributor Author

cjappl commented Aug 11, 2024

Thanks for the merge @vitalybuka !

I went ahead and requested commit access to LLVM, so I'll be able to merge things next time I get approvals. I hope that leads to less clerical tasks on your plate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants