Skip to content

Commit 0e23e79

Browse files
committed
First draft
1 parent fc8d773 commit 0e23e79

File tree

3 files changed

+155
-9
lines changed

3 files changed

+155
-9
lines changed

compiler-rt/lib/rtsan/rtsan_interceptors.cpp

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,25 @@ INTERCEPTOR(int, open, const char *path, int oflag, ...) {
7373
return result;
7474
}
7575

76+
#if SANITIZER_INTERCEPT_OPEN64
77+
INTERCEPTOR(int, open64, const char *path, int oflag, ...) {
78+
// TODO Establish whether we should intercept here if the flag contains
79+
// O_NONBLOCK
80+
__rtsan_expect_not_realtime("open64");
81+
82+
va_list args;
83+
va_start(args, oflag);
84+
const mode_t mode = va_arg(args, int);
85+
va_end(args);
86+
87+
const int result = REAL(open64)(path, oflag, mode);
88+
return result;
89+
}
90+
#define RTSAN_MAYBE_INTERCEPT_OPEN64 INTERCEPT_FUNCTION(open64)
91+
#else
92+
#define RTSAN_MAYBE_INTERCEPT_OPEN64
93+
#endif // SANITIZER_INTERCEPT_OPEN64
94+
7695
INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) {
7796
// TODO Establish whether we should intercept here if the flag contains
7897
// O_NONBLOCK
@@ -87,6 +106,25 @@ INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) {
87106
return result;
88107
}
89108

109+
#if SANITIZER_INTERCEPT_OPENAT64
110+
INTERCEPTOR(int, openat64, int fd, const char *path, int oflag, ...) {
111+
// TODO Establish whether we should intercept here if the flag contains
112+
// O_NONBLOCK
113+
__rtsan_expect_not_realtime("openat64");
114+
115+
va_list args;
116+
va_start(args, oflag);
117+
mode_t mode = va_arg(args, int);
118+
va_end(args);
119+
120+
const int result = REAL(openat64)(fd, path, oflag, mode);
121+
return result;
122+
}
123+
#define RTSAN_MAYBE_INTERCEPT_OPENAT64 INTERCEPT_FUNCTION(openat64)
124+
#else
125+
#define RTSAN_MAYBE_INTERCEPT_OPENAT64
126+
#endif // SANITIZER_INTERCEPT_OPENAT64
127+
90128
INTERCEPTOR(int, creat, const char *path, mode_t mode) {
91129
// TODO Establish whether we should intercept here if the flag contains
92130
// O_NONBLOCK
@@ -95,6 +133,19 @@ INTERCEPTOR(int, creat, const char *path, mode_t mode) {
95133
return result;
96134
}
97135

136+
#if SANITIZER_INTERCEPT_CREAT64
137+
INTERCEPTOR(int, creat64, const char *path, mode_t mode) {
138+
// TODO Establish whether we should intercept here if the flag contains
139+
// O_NONBLOCK
140+
__rtsan_expect_not_realtime("creat64");
141+
const int result = REAL(creat64)(path, mode);
142+
return result;
143+
}
144+
#define RTSAN_MAYBE_INTERCEPT_CREAT64 INTERCEPT_FUNCTION(creat64)
145+
#else
146+
#define RTSAN_MAYBE_INTERCEPT_CREAT64
147+
#endif // SANITIZER_INTERCEPT_CREAT64
148+
98149
INTERCEPTOR(int, fcntl, int filedes, int cmd, ...) {
99150
__rtsan_expect_not_realtime("fcntl");
100151

@@ -116,6 +167,32 @@ INTERCEPTOR(int, fcntl, int filedes, int cmd, ...) {
116167
return result;
117168
}
118169

170+
#if SANITIZER_INTERCEPT_FCNTL64
171+
INTERCEPTOR(int, fcntl64, int filedes, int cmd, ...) {
172+
__rtsan_expect_not_realtime("fcntl64");
173+
174+
va_list args;
175+
va_start(args, cmd);
176+
177+
// Following precedent here. The linux source (fcntl.c, do_fcntl) accepts the
178+
// final argument in a variable that will hold the largest of the possible
179+
// argument types (pointers and ints are typical in fcntl) It is then assumed
180+
// that the implementation of fcntl will cast it properly depending on cmd.
181+
//
182+
// This is also similar to what is done in
183+
// sanitizer_common/sanitizer_common_syscalls.inc
184+
const unsigned long arg = va_arg(args, unsigned long);
185+
int result = REAL(fcntl64)(filedes, cmd, arg);
186+
187+
va_end(args);
188+
189+
return result;
190+
}
191+
#define RTSAN_MAYBE_INTERCEPT_FCNTL64 INTERCEPT_FUNCTION(fcntl64)
192+
#else
193+
#define RTSAN_MAYBE_INTERCEPT_FCNTL64
194+
#endif // SANITIZER_INTERCEPT_FCNTL64
195+
119196
INTERCEPTOR(int, close, int filedes) {
120197
__rtsan_expect_not_realtime("close");
121198
return REAL(close)(filedes);
@@ -126,6 +203,16 @@ INTERCEPTOR(FILE *, fopen, const char *path, const char *mode) {
126203
return REAL(fopen)(path, mode);
127204
}
128205

206+
#if SANITIZER_INTERCEPT_FOPEN64
207+
INTERCEPTOR(FILE *, fopen64, const char *path, const char *mode) {
208+
__rtsan_expect_not_realtime("fopen64");
209+
return REAL(fopen64)(path, mode);
210+
}
211+
#define RTSAN_MAYBE_INTERCEPT_FOPEN64 INTERCEPT_FUNCTION(fopen64)
212+
#else
213+
#define RTSAN_MAYBE_INTERCEPT_FOPEN64
214+
#endif // SANITIZER_INTERCEPT_FOPEN64
215+
129216
INTERCEPTOR(size_t, fread, void *ptr, size_t size, size_t nitems,
130217
FILE *stream) {
131218
__rtsan_expect_not_realtime("fread");
@@ -169,6 +256,16 @@ INTERCEPTOR(ssize_t, pread, int fd, void *buf, size_t count, off_t offset) {
169256
return REAL(pread)(fd, buf, count, offset);
170257
}
171258

259+
#if SANITIZER_INTERCEPT_PREAD64
260+
INTERCEPTOR(ssize_t, pread64, int fd, void *buf, size_t count, off_t offset) {
261+
__rtsan_expect_not_realtime("pread64");
262+
return REAL(pread64)(fd, buf, count, offset);
263+
}
264+
#define RTSAN_MAYBE_INTERCEPT_PREAD64 INTERCEPT_FUNCTION(pread64)
265+
#else
266+
#define RTSAN_MAYBE_INTERCEPT_PREAD64
267+
#endif // SANITIZER_INTERCEPT_PREAD64
268+
172269
INTERCEPTOR(ssize_t, readv, int fd, const struct iovec *iov, int iovcnt) {
173270
__rtsan_expect_not_realtime("readv");
174271
return REAL(readv)(fd, iov, iovcnt);
@@ -180,6 +277,17 @@ INTERCEPTOR(ssize_t, pwrite, int fd, const void *buf, size_t count,
180277
return REAL(pwrite)(fd, buf, count, offset);
181278
}
182279

280+
#if SANITIZER_INTERCEPT_PWRITE64
281+
INTERCEPTOR(ssize_t, pwrite64, int fd, const void *buf, size_t count,
282+
off_t offset) {
283+
__rtsan_expect_not_realtime("pwrite64");
284+
return REAL(pwrite64)(fd, buf, count, offset);
285+
}
286+
#define RTSAN_MAYBE_INTERCEPT_PWRITE64 INTERCEPT_FUNCTION(pwrite64)
287+
#else
288+
#define RTSAN_MAYBE_INTERCEPT_PWRITE64
289+
#endif // SANITIZER_INTERCEPT_PWRITE64
290+
183291
INTERCEPTOR(ssize_t, writev, int fd, const struct iovec *iov, int iovcnt) {
184292
__rtsan_expect_not_realtime("writev");
185293
return REAL(writev)(fd, iov, iovcnt);
@@ -420,20 +528,27 @@ void __rtsan::InitializeInterceptors() {
420528
#endif
421529

422530
INTERCEPT_FUNCTION(open);
531+
RTSAN_MAYBE_INTERCEPT_OPEN64;
423532
INTERCEPT_FUNCTION(openat);
533+
RTSAN_MAYBE_INTERCEPT_OPENAT64;
424534
INTERCEPT_FUNCTION(close);
425535
INTERCEPT_FUNCTION(fopen);
536+
RTSAN_MAYBE_INTERCEPT_FOPEN64;
426537
INTERCEPT_FUNCTION(fread);
427538
INTERCEPT_FUNCTION(read);
428539
INTERCEPT_FUNCTION(write);
429540
INTERCEPT_FUNCTION(pread);
541+
RTSAN_MAYBE_INTERCEPT_PREAD64;
430542
INTERCEPT_FUNCTION(readv);
431543
INTERCEPT_FUNCTION(pwrite);
544+
RTSAN_MAYBE_INTERCEPT_PWRITE64;
432545
INTERCEPT_FUNCTION(writev);
433546
INTERCEPT_FUNCTION(fwrite);
434547
INTERCEPT_FUNCTION(fclose);
435548
INTERCEPT_FUNCTION(fcntl);
549+
RTSAN_MAYBE_INTERCEPT_FCNTL64;
436550
INTERCEPT_FUNCTION(creat);
551+
RTSAN_MAYBE_INTERCEPT_CREAT64;
437552
INTERCEPT_FUNCTION(puts);
438553
INTERCEPT_FUNCTION(fputs);
439554

compiler-rt/lib/rtsan/tests/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ foreach(arch ${RTSAN_TEST_ARCH})
7676
CFLAGS ${RTSAN_UNITTEST_CFLAGS} -fsanitize=realtime
7777
LINK_FLAGS ${RTSAN_UNITTEST_LINK_FLAGS} -fsanitize=realtime)
7878

79+
check_symbol_exists(__GLIBC__ stdio.h RTSAN_USING_GLIBC)
80+
if (RTSAN_USING_GLIBC)
81+
set(RtsanTestObjects_FileOffset64)
82+
generate_compiler_rt_tests(RtsanTestObjects_FileOffset64
83+
RtsanUnitTests "Rtsan-${arch}-FileOffset64-Test" ${arch}
84+
COMPILE_DEPS ${RTSAN_UNITTEST_HEADERS}
85+
SOURCES ${RTSAN_INST_TEST_SOURCES} ${COMPILER_RT_GOOGLETEST_SOURCES}
86+
DEPS rtsan
87+
CFLAGS ${RTSAN_UNITTEST_CFLAGS} -D_FILE_OFFSET_BITS=64 -fsanitize=realtime
88+
LINK_FLAGS ${RTSAN_UNITTEST_LINK_FLAGS} -fsanitize=realtime)
89+
endif()
90+
7991
set(RTSAN_TEST_RUNTIME RTRtsanTest.${arch})
8092
if(APPLE)
8193
set(RTSAN_TEST_RUNTIME_OBJECTS

compiler-rt/lib/rtsan/tests/rtsan_test_interceptors.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,24 @@
3737
#include <sys/socket.h>
3838
#include <sys/uio.h>
3939

40+
#if _FILE_OFFSET_BITS == 64 && SANITIZER_GLIBC
41+
const char *const kCreatFunctionName = "creat64";
42+
const char *const kFcntlFunctionName = "fcntl64";
43+
const char *const kFopenFunctionName = "fopen64";
44+
const char *const kOpenAtFunctionName = "openat64";
45+
const char *const kOpenFunctionName = "open64";
46+
const char *const kPreadFunctionName = "pread64";
47+
const char *const kPwriteFunctionName = "pwrite64";
48+
#else
49+
const char *const kCreatFunctionName = "creat";
50+
const char *const kFcntlFunctionName = "fcntl";
51+
const char *const kFopenFunctionName = "fopen";
52+
const char *const kOpenAtFunctionName = "openat";
53+
const char *const kOpenFunctionName = "open";
54+
const char *const kPreadFunctionName = "pread";
55+
const char *const kPwriteFunctionName = "pwrite";
56+
#endif
57+
4058
using namespace testing;
4159
using namespace rtsan_testing;
4260
using namespace std::chrono_literals;
@@ -183,13 +201,13 @@ TEST(TestRtsanInterceptors, NanosleepDiesWhenRealtime) {
183201

184202
TEST_F(RtsanFileTest, OpenDiesWhenRealtime) {
185203
auto func = [this]() { open(GetTemporaryFilePath(), O_RDONLY); };
186-
ExpectRealtimeDeath(func, "open");
204+
ExpectRealtimeDeath(func, kOpenFunctionName);
187205
ExpectNonRealtimeSurvival(func);
188206
}
189207

190208
TEST_F(RtsanFileTest, OpenatDiesWhenRealtime) {
191209
auto func = [this]() { openat(0, GetTemporaryFilePath(), O_RDONLY); };
192-
ExpectRealtimeDeath(func, "openat");
210+
ExpectRealtimeDeath(func, kOpenAtFunctionName);
193211
ExpectNonRealtimeSurvival(func);
194212
}
195213

@@ -214,13 +232,13 @@ TEST_F(RtsanFileTest, OpenCreatesFileWithProperMode) {
214232

215233
TEST_F(RtsanFileTest, CreatDiesWhenRealtime) {
216234
auto func = [this]() { creat(GetTemporaryFilePath(), S_IWOTH | S_IROTH); };
217-
ExpectRealtimeDeath(func, "creat");
235+
ExpectRealtimeDeath(func, kCreatFunctionName);
218236
ExpectNonRealtimeSurvival(func);
219237
}
220238

221239
TEST(TestRtsanInterceptors, FcntlDiesWhenRealtime) {
222240
auto func = []() { fcntl(0, F_GETFL); };
223-
ExpectRealtimeDeath(func, "fcntl");
241+
ExpectRealtimeDeath(func, kFcntlFunctionName);
224242
ExpectNonRealtimeSurvival(func);
225243
}
226244

@@ -239,7 +257,7 @@ TEST_F(RtsanFileTest, FcntlFlockDiesWhenRealtime) {
239257
ASSERT_THAT(fcntl(fd, F_GETLK, &lock), Eq(0));
240258
ASSERT_THAT(lock.l_type, F_UNLCK);
241259
};
242-
ExpectRealtimeDeath(func, "fcntl");
260+
ExpectRealtimeDeath(func, kFcntlFunctionName);
243261
ExpectNonRealtimeSurvival(func);
244262

245263
close(fd);
@@ -261,7 +279,7 @@ TEST_F(RtsanFileTest, FcntlSetFdDiesWhenRealtime) {
261279
ASSERT_THAT(fcntl(fd, F_GETFD), Eq(old_flags));
262280
};
263281

264-
ExpectRealtimeDeath(func, "fcntl");
282+
ExpectRealtimeDeath(func, kFcntlFunctionName);
265283
ExpectNonRealtimeSurvival(func);
266284

267285
close(fd);
@@ -278,7 +296,8 @@ TEST_F(RtsanFileTest, FopenDiesWhenRealtime) {
278296
auto fd = fopen(GetTemporaryFilePath(), "w");
279297
EXPECT_THAT(fd, Ne(nullptr));
280298
};
281-
ExpectRealtimeDeath(func, "fopen");
299+
300+
ExpectRealtimeDeath(func, kFopenFunctionName);
282301
ExpectNonRealtimeSurvival(func);
283302
}
284303

@@ -366,7 +385,7 @@ TEST_F(RtsanOpenedFileTest, PreadDiesWhenRealtime) {
366385
char c{};
367386
pread(GetOpenFd(), &c, 1, 0);
368387
};
369-
ExpectRealtimeDeath(Func, "pread");
388+
ExpectRealtimeDeath(Func, kPreadFunctionName);
370389
ExpectNonRealtimeSurvival(Func);
371390
}
372391

@@ -385,7 +404,7 @@ TEST_F(RtsanOpenedFileTest, PwriteDiesWhenRealtime) {
385404
char c = 'a';
386405
pwrite(GetOpenFd(), &c, 1, 0);
387406
};
388-
ExpectRealtimeDeath(Func, "pwrite");
407+
ExpectRealtimeDeath(Func, kPwriteFunctionName);
389408
ExpectNonRealtimeSurvival(Func);
390409
}
391410

0 commit comments

Comments
 (0)