-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[LLVM][rtsan] Add nosanitize_realtime instrumentation #106125
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
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
llvm/test/Instrumentation/RealtimeSanitizer/rtsan_nosanitize.ll
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
; RUN: opt < %s -passes=rtsan -S | FileCheck %s | ||
|
||
define void @nosanitized_function() #0 { | ||
%1 = alloca ptr, align 8 | ||
%2 = call ptr @malloc(i64 noundef 2) #3 | ||
store ptr %2, ptr %1, align 8 | ||
ret void | ||
} | ||
|
||
declare ptr @malloc(i64 noundef) #1 | ||
|
||
define noundef i32 @main() #2 { | ||
%1 = alloca i32, align 4 | ||
store i32 0, ptr %1, align 4 | ||
call void @nosanitized_function() #4 | ||
ret i32 0 | ||
} | ||
|
||
attributes #0 = { nosanitize_realtime } | ||
|
||
; CHECK-LABEL: @nosanitized_function() | ||
; CHECK-NEXT: call{{.*}}@__rtsan_off | ||
|
||
; CHECK: call{{.*}}@__rtsan_on | ||
; CHECK-NEXT: ret{{.*}}void |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need NoSanitizeRealtime, when Address and Memory sanitizers can exist without them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main reason this is necessary is we need to have a way to turn off the rtsan stack for all function calls below the function with the nosanitize attribute.
If you mark a function as needing the real-time sanitizer, all functions invoked by that function are subject to it's constraints (no allocations, no locks, no system calls). This is enforced via a stack, which is popped or pushed via __rtsan_realtime_enter and __rtsan_realtime_exit, inserted in this file.
When you mark a function as not needing to be inspected by the realtime sanitizer, it must change the stack such so these constraints are no longer in place. The nosanitize function AS WELL AS functions invoked by it can allocate, take locks, or call system calls.
Address and Memory sanitizer don't have this hierarchical model.
To make the example concrete...
Realtime sanitizer
Marking parent with no_sanitize("realtime") disables the realtime sanitizer for this function and all functions this function calls.
Address sanitizer, does not work like this, if you try to do something similar:
The nosanitize attribute only turns it off for that particular function, not "down the stack"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess another way to say the same thing as the previous comment:
ASan instruments and inspects every function in a binary. Asan disables on a per function basis.
RTSan instruments and inspects only in a specific context. RTSan disables on a per context basis.
This is the root of the difference and why we have to disable in this way, we are keeping state that tracks if we are in the context our sanitizer cares about.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why it needs to be attribute?
I think it's unusual, not sure if there is example at all, when fn attribute affects callees.
__lsan::ScopedDisabler
achieves the same without this confusion using language and even can be more precise, by limiting itself to a code block.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing that out, I wasn't aware it existed!
Pros of ScopedDisabler:
Cons of ScopedDisabler:
-fsanitize=realtime
.The biggest concern is that second "con" -- users would need to manually include out-of-project headers and manage build conditions, leading to some potential issues:
The
nosanitize
attribute is comparatively simpler, which "just works" without extra steps. I would prefer whatever solution we go forward with, it uses a construct that would be as non-invasive as the nosanitize approach to avoid burdening users with additional setup. Are there other solutions that provide this level of ease to the end user?For finer-grained interception, we've advised extracting code into new functions and applying the nosanitize attribute. This approach is a little more invasive but clearly indicates that the code is treated differently.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
conditions should not be a problem if you check __feature in rtsan header.
So it could be included unconditionally, and just compile into no-op without RTSan
we should do the same for all sanitizers, we have some inconsistency there.
Code modification is needed. It should be either attribute or C++ object either way, so I don't see much difference in duplication.
Should be unconditional. Header installed with clang.
However with g++ it may need a condition.
But I don't think it's a big issue. We used to preprocessor in C++.
Why it's a problem? They can do so even you go with existing attribute. I am 100% sure that ScopedDisabler like will be needed, as function scope may affect to much.
Also inliner and other passes can be affected by attribute. Regular C++ code will be more predictable for end user.
lsan has larger user base then rtsan, at least for now, and it was never an issue. Attribute approach can work for lsan as well.
I am not aware of context for this, can you point me there? How attribute is better here then ScopedDisabler?
So unless we have strong reason, I would prefer we solve the same problem in all component consistently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate on this, perhaps with a small code example? I think if this were possible my concern would be alleviated!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(actually, I think I have it figured out, going to test this for a little bit and get back to you. Thanks for the guidance)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works great for us @vitalybuka ! Thanks for explaining this to me. You will see some follow up reviews today that accomplish this goal.
Closing this review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That review is posted here: #106736