Skip to content

[compiler-rt][rtsan] Introduce rtsan_interface.h and ScopedDisabler #106736

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 7 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler-rt/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ if (COMPILER_RT_BUILD_SANITIZERS)
sanitizer/lsan_interface.h
sanitizer/msan_interface.h
sanitizer/netbsd_syscall_hooks.h
sanitizer/rtsan_interface.h
sanitizer/scudo_interface.h
sanitizer/tsan_interface.h
sanitizer/tsan_interface_atomic.h
Expand Down
75 changes: 75 additions & 0 deletions compiler-rt/include/sanitizer/rtsan_interface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//===-- sanitizer/rtsan_interface.h -----------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of RealtimeSanitizer.
//
// Public interface header.
//===----------------------------------------------------------------------===//

#ifndef SANITIZER_RTSAN_INTERFACE_H
#define SANITIZER_RTSAN_INTERFACE_H

#include <sanitizer/common_interface_defs.h>

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

// Disable all RTSan error reporting.
// Must be paired with a call to `__rtsan_enable`
void SANITIZER_CDECL __rtsan_disable(void);

// Re-enable all RTSan error reporting.
// Must follow a call to `__rtsan_disable`.
void SANITIZER_CDECL __rtsan_enable(void);

#ifdef __cplusplus
} // extern "C"

namespace __rtsan {
#if defined(__has_feature) && __has_feature(realtime_sanitizer)

class ScopedDisabler {
public:
ScopedDisabler() { __rtsan_disable(); }
~ScopedDisabler() { __rtsan_enable(); }

#if __cplusplus >= 201103L
ScopedDisabler(const ScopedDisabler &) = delete;
ScopedDisabler &operator=(const ScopedDisabler &) = delete;
ScopedDisabler(ScopedDisabler &&) = delete;
ScopedDisabler &operator=(ScopedDisabler &&) = delete;
#else
private:
ScopedDisabler(const ScopedDisabler &);
ScopedDisabler &operator=(const ScopedDisabler &);
#endif // __cplusplus >= 201103L
};

#else

class ScopedDisabler {
public:
ScopedDisabler() {}
#if __cplusplus >= 201103L
ScopedDisabler(const ScopedDisabler &) = delete;
ScopedDisabler &operator=(const ScopedDisabler &) = delete;
ScopedDisabler(ScopedDisabler &&) = delete;
ScopedDisabler &operator=(ScopedDisabler &&) = delete;
#else
private:
ScopedDisabler(const ScopedDisabler &);
ScopedDisabler &operator=(const ScopedDisabler &);
#endif // __cplusplus >= 201103L
};

#endif // defined(__has_feature) && __has_feature(realtime_sanitizer)
} // namespace __rtsan
#endif // __cplusplus

#endif // SANITIZER_RTSAN_INTERFACE_H
6 changes: 2 additions & 4 deletions compiler-rt/lib/rtsan/rtsan.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,10 @@ SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_enter();
// intercepted method calls to the real methods.
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_realtime_exit();

// Disable all RTSan error reporting.
// Injected into the code if "nosanitize(realtime)" is on a function.
// See documentation in rtsan_interface.h.
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_disable();

// Re-enable all RTSan error reporting.
// The counterpart to `__rtsan_disable`.
// See documentation in rtsan_interface.h.
SANITIZER_INTERFACE_ATTRIBUTE void __rtsan_enable();

SANITIZER_INTERFACE_ATTRIBUTE void
Expand Down
53 changes: 53 additions & 0 deletions compiler-rt/test/rtsan/disabler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// RUN: %clangxx -fsanitize=realtime %s -o %t
// RUN: not %run %t 2>&1 | FileCheck %s
// RUN: %clangxx %s -fsanitize=realtime -o - -S -emit-llvm | FileCheck %s --check-prefix=CHECK-ENABLED-IR
// RUN: %clangxx %s -o - -S -emit-llvm | FileCheck %s --check-prefix=CHECK-DISABLED-IR
// UNSUPPORTED: ios

#include <stdio.h>
#include <stdlib.h>

#include "sanitizer/rtsan_interface.h"

void violation() [[clang::nonblocking]] {
void *ptr;
{
__rtsan::ScopedDisabler disabler{};
ptr = malloc(2);
fprintf(stderr, "Allocated pointer %p in disabled context\n", ptr);
}

// ensure nested disablers don't interfere with one another
{
void *ptr2;
__rtsan::ScopedDisabler disabler{};
{
__rtsan::ScopedDisabler disabler2{};
ptr2 = malloc(2);
fprintf(stderr, "Allocated second pointer %p in disabled context\n",
ptr2);
}

free(ptr2);
fprintf(stderr, "Free'd second pointer in disabled context\n");
}

free(ptr);
}

int main() {
violation();
return 0;
// CHECK: Allocated pointer {{.*}} in disabled context
// CHECK: Allocated second pointer {{.*}} in disabled context
// CHECK: Free'd second pointer in disabled context
// CHECK: {{.*Real-time violation.*}}
// CHECK-NOT: {{.*malloc*}}
// CHECK-NEXT: {{.*free.*}}
}

// CHECK-ENABLED-IR: {{.*@__rtsan_disable.*}}
// CHECK-ENABLED-IR: {{.*@__rtsan_enable.*}}

// CHECK-DISABLED-IR-NOT: {{.*__rtsan_disable.*}}
// CHECK-DISABLED-IR-NOT: {{.*__rtsan_enable.*}}
Loading