[llvm] [LLVM][rtsan] Add nosanitize_realtime instrumentation (PR #106125)

Chris Apple via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 27 17:25:54 PDT 2024


================
@@ -51,6 +53,7 @@ RealtimeSanitizerPass::RealtimeSanitizerPass(
 PreservedAnalyses RealtimeSanitizerPass::run(Function &F,
                                              AnalysisManager<Function> &AM) {
   if (F.hasFnAttribute(Attribute::SanitizeRealtime)) {
+    assert(!F.hasFnAttribute(Attribute::NoSanitizeRealtime));
----------------
cjappl wrote:

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

```cpp
int ChildWithViolation() {
  int* v = new int[100]; // SHOULD BE VIOLATION, can't alloc in nonblocking context
}

__attribute__((no_sanitize("realtime")))
int Parent() {
  return ChildWithViolation(); // does not throw an error, because we are within a no_sanitize("realtime") context
}

int main() [[clang::nonblocking]]{
  Parent();
}
```

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:

```cpp
int ChildWithViolation() {
  int* v = new int[100];
  return v[100];
}

__attribute__((no_sanitize("address")))
int Parent() {
  return ChildWithViolation();
}

int main() {
  Parent();

 	return 0;
}
```

```sh
> ./build/helloWorld
=================================================================
==24510==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x000107915bd0 at pc 0x000104ea3e14 bp 0x00016af5e950 sp 0x00016af5e948
READ of size 4 at 0x000107915bd0 thread T0
    #0 0x104ea3e10 in ChildWithViolation() main.cpp:17
    #1 0x104ea3e34 in Parent() main.cpp:22
    #2 0x104ea3e58 in main main.cpp:26
    #3 0x1958960dc  (<unknown module>)
...
```

The nosanitize attribute only turns it off for that particular function, not "down the stack"

https://github.com/llvm/llvm-project/pull/106125


More information about the llvm-commits mailing list