[compiler-rt] compiler-rt: intercept fortified read/pread wrappers (PR #206228)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 27 06:45:28 PDT 2026
https://github.com/maflcko updated https://github.com/llvm/llvm-project/pull/206228
>From fae3e45abd4cf54eb7d9bb6c921a359450c62890 Mon Sep 17 00:00:00 2001
From: MarcoFalke <*~=`'#}+{/-|&$^_ at 721217.xyz>
Date: Sat, 27 Jun 2026 08:24:04 +0200
Subject: [PATCH 1/4] tsan: intercept fortified read/pread wrappers
Add TSAN/common interceptors for glibc fortified read/pread calls, so
that they follow the same blocking and signal-handling path as the plain
libc symbols.
The regression test fails without the new interceptors.
---
.../sanitizer_common_interceptors.inc | 55 +++++++++++++++++++
.../sanitizer_platform_interceptors.h | 3 +
compiler-rt/test/tsan/signal_in_read.c | 1 +
3 files changed, 59 insertions(+)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index c76010e77d1fa..412d5f9b37923 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -1026,6 +1026,23 @@ INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
#define INIT_READ
#endif
+#if SANITIZER_INTERCEPT___READ_CHK
+INTERCEPTOR(SSIZE_T, __read_chk, int fd, void *ptr, SIZE_T count,
+ SIZE_T buflen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __read_chk, fd, ptr, count, buflen);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(__read_chk)(fd, ptr, count,
+ buflen);
+ if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+#define INIT___READ_CHK COMMON_INTERCEPT_FUNCTION(__read_chk)
+#else
+#define INIT___READ_CHK
+#endif
+
#if SANITIZER_INTERCEPT_FREAD
INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
// libc file streams can call user-supplied functions, see fopencookie.
@@ -1061,6 +1078,23 @@ INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
#define INIT_PREAD
#endif
+#if SANITIZER_INTERCEPT___PREAD_CHK
+INTERCEPTOR(SSIZE_T, __pread_chk, int fd, void *ptr, SIZE_T count,
+ OFF_T offset, SIZE_T buflen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __pread_chk, fd, ptr, count, offset, buflen);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(__pread_chk)(fd, ptr, count,
+ offset, buflen);
+ if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+#define INIT___PREAD_CHK COMMON_INTERCEPT_FUNCTION(__pread_chk)
+#else
+#define INIT___PREAD_CHK
+#endif
+
#if SANITIZER_INTERCEPT_PREAD64
INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
void *ctx;
@@ -1079,6 +1113,24 @@ INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
#define INIT_PREAD64
#endif
+#if SANITIZER_INTERCEPT___PREAD64_CHK
+INTERCEPTOR(SSIZE_T, __pread64_chk, int fd, void *ptr, SIZE_T count,
+ OFF64_T offset, SIZE_T buflen) {
+ void *ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __pread64_chk, fd, ptr, count, offset,
+ buflen);
+ COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+ SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(__pread64_chk)(fd, ptr, count,
+ offset, buflen);
+ if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
+ if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ return res;
+}
+#define INIT___PREAD64_CHK COMMON_INTERCEPT_FUNCTION(__pread64_chk)
+#else
+#define INIT___PREAD64_CHK
+#endif
+
#if SANITIZER_INTERCEPT_READV
INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
int iovcnt) {
@@ -10431,9 +10483,12 @@ static void InitializeCommonInterceptors() {
INIT_MEMRCHR;
INIT_MEMMEM;
INIT_READ;
+ INIT___READ_CHK;
INIT_FREAD;
INIT_PREAD;
+ INIT___PREAD_CHK;
INIT_PREAD64;
+ INIT___PREAD64_CHK;
INIT_READV;
INIT_PREADV;
INIT_PREADV64;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
index 9f6fc4e9b9bfa..702c960434a0f 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h
@@ -201,6 +201,9 @@ SANITIZER_WEAK_IMPORT void *aligned_alloc(__sanitizer::usize __alignment,
#define SANITIZER_INTERCEPT_READ SI_POSIX
#define SANITIZER_INTERCEPT_PREAD SI_POSIX
+#define SANITIZER_INTERCEPT___READ_CHK SI_GLIBC
+#define SANITIZER_INTERCEPT___PREAD_CHK SI_GLIBC
+#define SANITIZER_INTERCEPT___PREAD64_CHK SI_GLIBC
#define SANITIZER_INTERCEPT_WRITE SI_POSIX
#define SANITIZER_INTERCEPT_PWRITE SI_POSIX
diff --git a/compiler-rt/test/tsan/signal_in_read.c b/compiler-rt/test/tsan/signal_in_read.c
index ec50d9d021745..82f9a58e46da5 100644
--- a/compiler-rt/test/tsan/signal_in_read.c
+++ b/compiler-rt/test/tsan/signal_in_read.c
@@ -1,4 +1,5 @@
// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+// RUN: %clang_tsan -O1 -D_FORTIFY_SOURCE=3 %s -o %t.fortify && %run %t.fortify 2>&1 | FileCheck %s
#include "test.h"
>From e6fa473d2da26191b2931d3c6539a956248e3a4d Mon Sep 17 00:00:00 2001
From: MarcoFalke <*~=`'#}+{/-|&$^_ at 721217.xyz>
Date: Sat, 27 Jun 2026 10:12:38 +0200
Subject: [PATCH 2/4] git show HEAD~ -U0 |
clang/tools/clang-format/clang-format-diff.py -p1 -i -v
---
.../sanitizer_common_interceptors.inc | 51 ++++++++++---------
1 file changed, 28 insertions(+), 23 deletions(-)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 412d5f9b37923..caf5a039263f0 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -1027,20 +1027,22 @@ INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
#endif
#if SANITIZER_INTERCEPT___READ_CHK
-INTERCEPTOR(SSIZE_T, __read_chk, int fd, void *ptr, SIZE_T count,
+INTERCEPTOR(SSIZE_T, __read_chk, int fd, void* ptr, SIZE_T count,
SIZE_T buflen) {
- void *ctx;
+ void* ctx;
COMMON_INTERCEPTOR_ENTER(ctx, __read_chk, fd, ptr, count, buflen);
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
- SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(__read_chk)(fd, ptr, count,
- buflen);
- if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
- if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ SSIZE_T res =
+ COMMON_INTERCEPTOR_BLOCK_REAL(__read_chk)(fd, ptr, count, buflen);
+ if (res > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
+ if (res >= 0 && fd >= 0)
+ COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
return res;
}
-#define INIT___READ_CHK COMMON_INTERCEPT_FUNCTION(__read_chk)
+# define INIT___READ_CHK COMMON_INTERCEPT_FUNCTION(__read_chk)
#else
-#define INIT___READ_CHK
+# define INIT___READ_CHK
#endif
#if SANITIZER_INTERCEPT_FREAD
@@ -1079,20 +1081,22 @@ INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
#endif
#if SANITIZER_INTERCEPT___PREAD_CHK
-INTERCEPTOR(SSIZE_T, __pread_chk, int fd, void *ptr, SIZE_T count,
- OFF_T offset, SIZE_T buflen) {
- void *ctx;
+INTERCEPTOR(SSIZE_T, __pread_chk, int fd, void* ptr, SIZE_T count, OFF_T offset,
+ SIZE_T buflen) {
+ void* ctx;
COMMON_INTERCEPTOR_ENTER(ctx, __pread_chk, fd, ptr, count, offset, buflen);
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(__pread_chk)(fd, ptr, count,
offset, buflen);
- if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
- if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ if (res > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
+ if (res >= 0 && fd >= 0)
+ COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
return res;
}
-#define INIT___PREAD_CHK COMMON_INTERCEPT_FUNCTION(__pread_chk)
+# define INIT___PREAD_CHK COMMON_INTERCEPT_FUNCTION(__pread_chk)
#else
-#define INIT___PREAD_CHK
+# define INIT___PREAD_CHK
#endif
#if SANITIZER_INTERCEPT_PREAD64
@@ -1114,21 +1118,22 @@ INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
#endif
#if SANITIZER_INTERCEPT___PREAD64_CHK
-INTERCEPTOR(SSIZE_T, __pread64_chk, int fd, void *ptr, SIZE_T count,
+INTERCEPTOR(SSIZE_T, __pread64_chk, int fd, void* ptr, SIZE_T count,
OFF64_T offset, SIZE_T buflen) {
- void *ctx;
- COMMON_INTERCEPTOR_ENTER(ctx, __pread64_chk, fd, ptr, count, offset,
- buflen);
+ void* ctx;
+ COMMON_INTERCEPTOR_ENTER(ctx, __pread64_chk, fd, ptr, count, offset, buflen);
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(__pread64_chk)(fd, ptr, count,
offset, buflen);
- if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
- if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+ if (res > 0)
+ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
+ if (res >= 0 && fd >= 0)
+ COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
return res;
}
-#define INIT___PREAD64_CHK COMMON_INTERCEPT_FUNCTION(__pread64_chk)
+# define INIT___PREAD64_CHK COMMON_INTERCEPT_FUNCTION(__pread64_chk)
#else
-#define INIT___PREAD64_CHK
+# define INIT___PREAD64_CHK
#endif
#if SANITIZER_INTERCEPT_READV
>From bfe0e9ea4165eddb911a9d0784de5ce120d3cfc8 Mon Sep 17 00:00:00 2001
From: MarcoFalke <*~=`'#}+{/-|&$^_ at 721217.xyz>
Date: Sat, 27 Jun 2026 10:20:25 +0200
Subject: [PATCH 3/4] hwasan: Add exclusions I missed
Otherwise, the CI fails:
2026-06-27T08:00:27.3342582Z FAILED: compiler-rt/lib/hwasan/CMakeFiles/RTHwasan.x86_64.dir/hwasan_interceptors.cpp.o
2026-06-27T08:00:27.3355912Z /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/clang++ --target=x86_64-unknown-linux-gnu -DHWASAN_WITH_INTERCEPTORS=1 -D_DEBUG -D_GLIBCXX_ASSERTIONS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/lib/hwasan/.. -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wno-pass-failed -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Xclang -fno-pch-timestamp -Wall -Werror -Wno-unused-parameter -O3 -DNDEBUG -std=c++17 -m64 -fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer -funwind-tables -fno-stack-protector -fno-sanitize=safe-stack -fvisibility=hidden -fno-lto -Wthread-safety -Wthread-safety-reference -Wthread-safety-beta -O3 -gline-tables-only -Wno-gnu -Wno-variadic-macros -Wno-c99-extensions -ftrivial-auto-var-init=pattern -nostdinc++ -fno-rtti -ffreestanding -Wno-format -MD -MT compiler-rt/lib/hwasan/CMakeFiles/RTHwasan.x86_64.dir/hwasan_interceptors.cpp.o -MF compiler-rt/lib/hwasan/CMakeFiles/RTHwasan.x86_64.dir/hwasan_interceptors.cpp.o.d -o compiler-rt/lib/hwasan/CMakeFiles/RTHwasan.x86_64.dir/hwasan_interceptors.cpp.o -c /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/lib/hwasan/hwasan_interceptors.cpp
2026-06-27T08:00:27.3381929Z In file included from /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/lib/hwasan/hwasan_interceptors.cpp:246:
2026-06-27T08:00:27.3432440Z /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/lib/hwasan/../sanitizer_common/sanitizer_common_interceptors.inc:1035:17: error: expected expression
2026-06-27T08:00:27.3434279Z 1035 | SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(__read_chk)(fd, ptr, count,
2026-06-27T08:00:27.3501560Z | ^
2026-06-27T08:00:27.3532449Z /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/lib/hwasan/hwasan_interceptors.cpp:145:7: note: expanded from macro 'COMMON_INTERCEPTOR_BLOCK_REAL'
2026-06-27T08:00:27.3551761Z 145 | do { \
2026-06-27T08:00:27.3571271Z | ^
2026-06-27T08:00:27.3631993Z In file included from /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/lib/hwasan/hwasan_interceptors.cpp:246:
2026-06-27T08:00:27.3634439Z /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/lib/hwasan/../sanitizer_common/sanitizer_common_interceptors.inc:1087:17: error: expected expression
2026-06-27T08:00:27.3636586Z 1087 | SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(__pread_chk)(fd, ptr, count,
2026-06-27T08:00:27.3637589Z | ^
2026-06-27T08:00:27.3639213Z /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/lib/hwasan/hwasan_interceptors.cpp:145:7: note: expanded from macro 'COMMON_INTERCEPTOR_BLOCK_REAL'
2026-06-27T08:00:27.3641242Z 145 | do { \
2026-06-27T08:00:27.3641897Z | ^
2026-06-27T08:00:27.3643134Z In file included from /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/lib/hwasan/hwasan_interceptors.cpp:246:
2026-06-27T08:00:27.3645679Z /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/lib/hwasan/../sanitizer_common/sanitizer_common_interceptors.inc:1123:17: error: expected expression
2026-06-27T08:00:27.3647667Z 1123 | SSIZE_T res = COMMON_INTERCEPTOR_BLOCK_REAL(__pread64_chk)(fd, ptr, count,
2026-06-27T08:00:27.3648524Z | ^
2026-06-27T08:00:27.3649947Z /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/lib/hwasan/hwasan_interceptors.cpp:145:7: note: expanded from macro 'COMMON_INTERCEPTOR_BLOCK_REAL'
2026-06-27T08:00:27.3651681Z 145 | do { \
2026-06-27T08:00:27.3652239Z | ^
2026-06-27T08:00:27.3652627Z 3 errors generated.
---
compiler-rt/lib/hwasan/hwasan_platform_interceptors.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h b/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h
index 8a653d83dec65..3936e167e2dbc 100644
--- a/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h
+++ b/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h
@@ -89,9 +89,15 @@
#undef SANITIZER_INTERCEPT_READ
#define SANITIZER_INTERCEPT_READ 0
+#undef SANITIZER_INTERCEPT___READ_CHK
+#define SANITIZER_INTERCEPT___READ_CHK 0
+
#undef SANITIZER_INTERCEPT_PREAD
#define SANITIZER_INTERCEPT_PREAD 0
+#undef SANITIZER_INTERCEPT___PREAD_CHK
+#define SANITIZER_INTERCEPT___PREAD_CHK 0
+
#undef SANITIZER_INTERCEPT_WRITE
#define SANITIZER_INTERCEPT_WRITE 0
@@ -116,6 +122,9 @@
#undef SANITIZER_INTERCEPT_PREAD64
#define SANITIZER_INTERCEPT_PREAD64 0
+#undef SANITIZER_INTERCEPT___PREAD64_CHK
+#define SANITIZER_INTERCEPT___PREAD64_CHK 0
+
#undef SANITIZER_INTERCEPT_PWRITE64
#define SANITIZER_INTERCEPT_PWRITE64 0
>From faf8fd95b6099f1437a9597e21e12a24f1daacdb Mon Sep 17 00:00:00 2001
From: MarcoFalke <*~=`'#}+{/-|&$^_ at 721217.xyz>
Date: Sat, 27 Jun 2026 15:40:38 +0200
Subject: [PATCH 4/4] sanitizer_common: add checked read smoke test (glibc
_FORTIFY_SOURCE=3)
---
.../TestCases/Linux/read_pread_chk.c | 43 +++++++++++++++++++
1 file changed, 43 insertions(+)
create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Linux/read_pread_chk.c
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/read_pread_chk.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/read_pread_chk.c
new file mode 100644
index 0000000000000..54fa3afd52dfd
--- /dev/null
+++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/read_pread_chk.c
@@ -0,0 +1,43 @@
+// RUN: %clang -O1 %s -o %t && %run %t
+// RUN: %clang -O1 -D_FORTIFY_SOURCE=3 %s -o %t.fortify && %run %t.fortify
+// REQUIRES: glibc
+
+#define _LARGEFILE64_SOURCE
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void write_all(int fd, const char *s) {
+ size_t n = strlen(s);
+ assert(write(fd, s, n) == (ssize_t)n);
+}
+
+int main(void) {
+ char path[] = "/tmp/sanitizer_common_io_XXXXXX";
+ int fd = mkstemp(path);
+ assert(fd >= 0);
+ unlink(path);
+
+ write_all(fd, "abcdef");
+ assert(lseek(fd, 0, SEEK_SET) == 0);
+
+ char buf[8];
+ memset(buf, 0, sizeof(buf));
+ assert(read(fd, buf, 1) == 1);
+ assert(buf[0] == 'a');
+
+ memset(buf, 0, sizeof(buf));
+ assert(pread(fd, buf, 1, 2) == 1);
+ assert(buf[0] == 'c');
+
+ memset(buf, 0, sizeof(buf));
+ assert(pread64(fd, buf, 1, 4) == 1);
+ assert(buf[0] == 'e');
+
+ assert(close(fd) == 0);
+ return 0;
+}
More information about the llvm-commits
mailing list