[clang] [compiler-rt] [rtsan] Enable RealtimeSanitizer for FreeBSD (PR #125389)
David CARLIER via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 7 05:21:43 PST 2025
https://github.com/devnexen updated https://github.com/llvm/llvm-project/pull/125389
>From e40672e8137c0546b1604795901ccea8b15f7932 Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen at gmail.com>
Date: Sun, 2 Feb 2025 09:36:50 +0000
Subject: [PATCH 1/3] [compiler-rt][rtsan] porting the sanitizer to FreeBSD.
Most of the apple api exceptions also apply to freebsd, however
to create a per-thread realtime context pthread api cannot be used
since freebsd calls calloc in _thr_alloc().
---
compiler-rt/lib/rtsan/rtsan_context.cpp | 16 ++++++++++++++++
.../lib/rtsan/rtsan_interceptors_posix.cpp | 4 ++--
.../tests/rtsan_test_interceptors_posix.cpp | 4 +++-
3 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/compiler-rt/lib/rtsan/rtsan_context.cpp b/compiler-rt/lib/rtsan/rtsan_context.cpp
index 536d62e81e2fb66..dacc9b6dedf4029 100644
--- a/compiler-rt/lib/rtsan/rtsan_context.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_context.cpp
@@ -19,6 +19,7 @@
using namespace __sanitizer;
using namespace __rtsan;
+#if !SANITIZER_FREEBSD
static pthread_key_t context_key;
static pthread_once_t key_once = PTHREAD_ONCE_INIT;
@@ -43,6 +44,21 @@ static __rtsan::Context &GetContextForThisThreadImpl() {
return *current_thread_context;
}
+#else
+
+// On FreeBSD, pthread api cannot be used as calloc is called under the hood
+// at library initialization time.
+static __thread Context *ctx = nullptr;
+
+static __rtsan::Context &GetContextForThisThreadImpl() {
+ if (ctx == nullptr) {
+ ctx = static_cast<Context *>(MmapOrDie(sizeof(Context), "RtsanContext"));
+ new (ctx) Context();
+ }
+
+ return *ctx;
+}
+#endif
__rtsan::Context::Context() = default;
diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index 83e6cdd4a009410..b76413dc2e462f1 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -939,7 +939,7 @@ INTERCEPTOR(int, msync, void *addr, size_t length, int flag) {
return REAL(msync)(addr, length, flag);
}
-#if SANITIZER_APPLE
+#if SANITIZER_APPLE || SANITIZER_FREEBSD
INTERCEPTOR(int, mincore, const void *addr, size_t length, char *vec) {
#else
INTERCEPTOR(int, mincore, void *addr, size_t length, unsigned char *vec) {
@@ -1334,7 +1334,7 @@ INTERCEPTOR(ssize_t, process_vm_writev, pid_t pid,
// the test. Revisit this in the future, but hopefully intercepting fork/exec is
// enough to dissuade usage of wait by proxy.
-#if SANITIZER_APPLE
+#if SANITIZER_APPLE || SANITIZER_FREEBSD
#define INT_TYPE_SYSCALL int
#else
#define INT_TYPE_SYSCALL long
diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
index 075f5974b7562a8..e5290ababec6685 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
@@ -280,7 +280,7 @@ TEST_F(RtsanOpenedMmapTest, MsyncDiesWhenRealtime) {
}
TEST_F(RtsanOpenedMmapTest, MincoreDiesWhenRealtime) {
-#if SANITIZER_APPLE
+#if SANITIZER_APPLE || SANITIZER_FREEBSD
std::vector<char> vec(GetSize() / 1024);
#else
std::vector<unsigned char> vec(GetSize() / 1024);
@@ -1539,6 +1539,7 @@ TEST_F(KqueueTest, KeventDiesWhenRealtime) {
ExpectNonRealtimeSurvival(Func);
}
+#if SANITIZER_APPLE
TEST_F(KqueueTest, Kevent64DiesWhenRealtime) {
struct kevent64_s event;
EV_SET64(&event, 0, EVFILT_READ, EV_ADD, 0, 0, 0, 0, 0);
@@ -1551,6 +1552,7 @@ TEST_F(KqueueTest, Kevent64DiesWhenRealtime) {
ExpectRealtimeDeath(Func, "kevent64");
ExpectNonRealtimeSurvival(Func);
}
+#endif // SANITIZER_APPLE
#endif // SANITIZER_INTERCEPT_KQUEUE
#if SANITIZER_LINUX
>From 05ad49c3ff4fd185ab0618a1cfd05c2a86f36dcc Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen at gmail.com>
Date: Sun, 2 Feb 2025 09:38:52 +0000
Subject: [PATCH 2/3] freebsd clang frontend update.
---
clang/lib/Driver/ToolChains/FreeBSD.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index a6d859f0ebfec23..baabfabf26267f6 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -497,6 +497,7 @@ SanitizerMask FreeBSD::getSupportedSanitizers() const {
Res |= SanitizerKind::PointerCompare;
Res |= SanitizerKind::PointerSubtract;
Res |= SanitizerKind::Vptr;
+ Res |= SanitizerKind::Realtime;
if (IsAArch64 || IsX86_64 || IsMIPS64) {
Res |= SanitizerKind::Leak;
Res |= SanitizerKind::Thread;
>From 49a4564ac7a3e3042178817c407d32086bb543d3 Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen at gmail.com>
Date: Fri, 7 Feb 2025 13:19:37 +0000
Subject: [PATCH 3/3] using pthread api for context creation.
but disabling mmap interception for this platform, which is the root
cause of the previous infinite call recursion.
---
compiler-rt/cmake/config-ix.cmake | 4 ++--
compiler-rt/lib/rtsan/rtsan_context.cpp | 16 ----------------
.../lib/rtsan/rtsan_interceptors_posix.cpp | 16 ++++++++++++++--
.../tests/rtsan_test_interceptors_posix.cpp | 4 ++++
4 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake
index cf729c3adb1f5f5..b981db24942217f 100644
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -793,7 +793,7 @@ else()
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND RTSAN_SUPPORTED_ARCH AND
- OS_NAME MATCHES "Darwin|Linux")
+ OS_NAME MATCHES "Darwin|Linux|FreeBSD")
set(COMPILER_RT_HAS_RTSAN TRUE)
else()
set(COMPILER_RT_HAS_RTSAN FALSE)
@@ -850,7 +850,7 @@ else()
endif()
if (COMPILER_RT_HAS_SANITIZER_COMMON AND TYSAN_SUPPORTED_ARCH AND
- OS_NAME MATCHES "Linux|Darwin")
+ OS_NAME MATCHES "Linux|Darwin")
set(COMPILER_RT_HAS_TYSAN TRUE)
else()
set(COMPILER_RT_HAS_TYSAN FALSE)
diff --git a/compiler-rt/lib/rtsan/rtsan_context.cpp b/compiler-rt/lib/rtsan/rtsan_context.cpp
index dacc9b6dedf4029..536d62e81e2fb66 100644
--- a/compiler-rt/lib/rtsan/rtsan_context.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_context.cpp
@@ -19,7 +19,6 @@
using namespace __sanitizer;
using namespace __rtsan;
-#if !SANITIZER_FREEBSD
static pthread_key_t context_key;
static pthread_once_t key_once = PTHREAD_ONCE_INIT;
@@ -44,21 +43,6 @@ static __rtsan::Context &GetContextForThisThreadImpl() {
return *current_thread_context;
}
-#else
-
-// On FreeBSD, pthread api cannot be used as calloc is called under the hood
-// at library initialization time.
-static __thread Context *ctx = nullptr;
-
-static __rtsan::Context &GetContextForThisThreadImpl() {
- if (ctx == nullptr) {
- ctx = static_cast<Context *>(MmapOrDie(sizeof(Context), "RtsanContext"));
- new (ctx) Context();
- }
-
- return *ctx;
-}
-#endif
__rtsan::Context::Context() = default;
diff --git a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
index b76413dc2e462f1..8d4a16edb2ca8b6 100644
--- a/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/rtsan_interceptors_posix.cpp
@@ -864,11 +864,18 @@ INTERCEPTOR(void *, pvalloc, size_t size) {
#define RTSAN_MAYBE_INTERCEPT_PVALLOC
#endif
+#if !SANITIZER_FREEBSD
+// enabling this interception on freebsd leads to infinite recursion
+// on pthread lib initialization
INTERCEPTOR(void *, mmap, void *addr, size_t length, int prot, int flags,
int fd, off_t offset) {
__rtsan_notify_intercepted_call("mmap");
return REAL(mmap)(addr, length, prot, flags, fd, offset);
}
+#define RTSAN_MAYBE_INTERCEPT_MMAP INTERCEPT_FUNCTION(mmap)
+#else
+#define RTSAN_MAYBE_INTERCEPT_MMAP
+#endif // !SANITIZER_FREEBSD
#if SANITIZER_INTERCEPT_MMAP64
INTERCEPTOR(void *, mmap64, void *addr, size_t length, int prot, int flags,
@@ -907,10 +914,15 @@ INTERCEPTOR(void *, mremap, void *oaddr, size_t olength, size_t nlength,
#define RTSAN_MAYBE_INTERCEPT_MREMAP
#endif
+#if !SANITIZER_FREEBSD
INTERCEPTOR(int, munmap, void *addr, size_t length) {
__rtsan_notify_intercepted_call("munmap");
return REAL(munmap)(addr, length);
}
+#define RTSAN_MAYBE_INTERCEPT_MUNMAP INTERCEPT_FUNCTION(munmap)
+#else
+#define RTSAN_MAYBE_INTERCEPT_MUNMAP
+#endif
#if !SANITIZER_APPLE
INTERCEPTOR(int, madvise, void *addr, size_t length, int flag) {
@@ -1381,10 +1393,10 @@ void __rtsan::InitializeInterceptors() {
INTERCEPT_FUNCTION(valloc);
RTSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC;
INTERCEPT_FUNCTION(posix_memalign);
- INTERCEPT_FUNCTION(mmap);
+ RTSAN_MAYBE_INTERCEPT_MMAP;
RTSAN_MAYBE_INTERCEPT_MMAP64;
RTSAN_MAYBE_INTERCEPT_MREMAP;
- INTERCEPT_FUNCTION(munmap);
+ RTSAN_MAYBE_INTERCEPT_MUNMAP;
RTSAN_MAYBE_INTERCEPT_MADVISE;
RTSAN_MAYBE_INTERCEPT_POSIX_MADVISE;
INTERCEPT_FUNCTION(mprotect);
diff --git a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
index e5290ababec6685..6047a16aa1ff760 100644
--- a/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
+++ b/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors_posix.cpp
@@ -188,6 +188,7 @@ TEST(TestRtsanInterceptors, PvallocDiesWhenRealtime) {
}
#endif
+#if !SANITIZER_FREEBSD
TEST(TestRtsanInterceptors, MmapDiesWhenRealtime) {
auto Func = []() {
void *_ = mmap(nullptr, 8, PROT_READ | PROT_WRITE,
@@ -196,6 +197,7 @@ TEST(TestRtsanInterceptors, MmapDiesWhenRealtime) {
ExpectRealtimeDeath(Func, MAYBE_APPEND_64("mmap"));
ExpectNonRealtimeSurvival(Func);
}
+#endif
#if SANITIZER_LINUX
TEST(TestRtsanInterceptors, MremapDiesWhenRealtime) {
@@ -207,6 +209,7 @@ TEST(TestRtsanInterceptors, MremapDiesWhenRealtime) {
}
#endif
+#if !SANITIZER_FREEBSD
TEST(TestRtsanInterceptors, MunmapDiesWhenRealtime) {
void *ptr = mmap(nullptr, 8, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -216,6 +219,7 @@ TEST(TestRtsanInterceptors, MunmapDiesWhenRealtime) {
ExpectRealtimeDeath(Func, "munmap");
ExpectNonRealtimeSurvival(Func);
}
+#endif
class RtsanOpenedMmapTest : public RtsanFileTest {
protected:
More information about the llvm-commits
mailing list