1 | //===--- rtsan_test_interceptors.cpp - Realtime Sanitizer -------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | //===----------------------------------------------------------------------===// |
10 | |
11 | #include "sanitizer_common/sanitizer_platform.h" |
12 | #if SANITIZER_POSIX |
13 | |
14 | #include "gtest/gtest.h" |
15 | |
16 | #include "sanitizer_common/sanitizer_platform_interceptors.h" |
17 | |
18 | #include "rtsan_test_utilities.h" |
19 | |
20 | #if SANITIZER_APPLE |
21 | #include <libkern/OSAtomic.h> |
22 | #include <os/lock.h> |
23 | #include <unistd.h> |
24 | #endif |
25 | |
26 | #if SANITIZER_INTERCEPT_MEMALIGN || SANITIZER_INTERCEPT_PVALLOC |
27 | #include <malloc.h> |
28 | #endif |
29 | |
30 | #if SANITIZER_INTERCEPT_EPOLL |
31 | #include <sys/epoll.h> |
32 | #endif |
33 | |
34 | #if SANITIZER_INTERCEPT_KQUEUE |
35 | #include <sys/event.h> |
36 | #include <sys/time.h> |
37 | #endif |
38 | |
39 | #include <fcntl.h> |
40 | #include <ifaddrs.h> |
41 | #include <net/if.h> |
42 | #include <netdb.h> |
43 | #include <poll.h> |
44 | #include <pthread.h> |
45 | #include <stdio.h> |
46 | #if SANITIZER_LINUX |
47 | #include <sys/eventfd.h> |
48 | #include <sys/inotify.h> |
49 | #include <sys/timerfd.h> |
50 | #endif |
51 | #include <sys/ioctl.h> |
52 | #include <sys/mman.h> |
53 | #include <sys/socket.h> |
54 | #include <sys/stat.h> |
55 | #include <sys/syscall.h> |
56 | #include <sys/types.h> |
57 | #include <sys/uio.h> |
58 | |
59 | #if _FILE_OFFSET_BITS == 64 && SANITIZER_GLIBC |
60 | // Under these conditions, some system calls are `foo64` instead of `foo` |
61 | #define MAYBE_APPEND_64(func) func "64" |
62 | #else |
63 | #define MAYBE_APPEND_64(func) func |
64 | #endif |
65 | |
66 | using namespace testing; |
67 | using namespace rtsan_testing; |
68 | using namespace std::chrono_literals; |
69 | |
70 | // NOTE: In the socket tests we pass in bad info to the calls to ensure they |
71 | // fail which is why we EXPECT_NE 0 for their return codes. |
72 | // We just care that the call is intercepted |
73 | const int kNotASocketFd = 0; |
74 | |
75 | void *FakeThreadEntryPoint(void *) { return nullptr; } |
76 | |
77 | class RtsanFileTest : public ::testing::Test { |
78 | protected: |
79 | void SetUp() override { |
80 | const ::testing::TestInfo *const test_info = |
81 | ::testing::UnitTest::GetInstance()->current_test_info(); |
82 | file_path_ = std::string("/tmp/rtsan_temporary_test_file_" ) + |
83 | test_info->name() + ".txt" ; |
84 | RemoveTemporaryFile(); |
85 | } |
86 | |
87 | // Gets a file path with the test's name in it |
88 | // This file will be removed if it exists at the end of the test |
89 | const char *GetTemporaryFilePath() const { return file_path_.c_str(); } |
90 | |
91 | void TearDown() override { RemoveTemporaryFile(); } |
92 | |
93 | private: |
94 | void RemoveTemporaryFile() const { std::remove(filename: GetTemporaryFilePath()); } |
95 | std::string file_path_; |
96 | }; |
97 | |
98 | /* |
99 | Allocation and deallocation |
100 | */ |
101 | |
102 | TEST(TestRtsanInterceptors, MallocDiesWhenRealtime) { |
103 | auto Func = []() { EXPECT_NE(nullptr, malloc(size: 1)); }; |
104 | ExpectRealtimeDeath(Func, intercepted_method_name: "malloc" ); |
105 | ExpectNonRealtimeSurvival(Func); |
106 | } |
107 | |
108 | TEST(TestRtsanInterceptors, CallocDiesWhenRealtime) { |
109 | auto Func = []() { EXPECT_NE(nullptr, calloc(nmemb: 2, size: 4)); }; |
110 | ExpectRealtimeDeath(Func, intercepted_method_name: "calloc" ); |
111 | ExpectNonRealtimeSurvival(Func); |
112 | } |
113 | |
114 | TEST(TestRtsanInterceptors, ReallocDiesWhenRealtime) { |
115 | void *ptr_1 = malloc(size: 1); |
116 | auto Func = [ptr_1]() { EXPECT_NE(nullptr, realloc(ptr: ptr_1, size: 8)); }; |
117 | ExpectRealtimeDeath(Func, intercepted_method_name: "realloc" ); |
118 | ExpectNonRealtimeSurvival(Func); |
119 | } |
120 | |
121 | #if SANITIZER_APPLE |
122 | TEST(TestRtsanInterceptors, ReallocfDiesWhenRealtime) { |
123 | void *ptr_1 = malloc(1); |
124 | auto Func = [ptr_1]() { EXPECT_NE(nullptr, reallocf(ptr_1, 8)); }; |
125 | ExpectRealtimeDeath(Func, "reallocf" ); |
126 | ExpectNonRealtimeSurvival(Func); |
127 | } |
128 | #endif |
129 | |
130 | TEST(TestRtsanInterceptors, VallocDiesWhenRealtime) { |
131 | auto Func = []() { EXPECT_NE(nullptr, valloc(size: 4)); }; |
132 | ExpectRealtimeDeath(Func, intercepted_method_name: "valloc" ); |
133 | ExpectNonRealtimeSurvival(Func); |
134 | } |
135 | |
136 | #if __has_builtin(__builtin_available) && SANITIZER_APPLE |
137 | #define ALIGNED_ALLOC_AVAILABLE() (__builtin_available(macOS 10.15, *)) |
138 | #else |
139 | // We are going to assume this is true until we hit systems where it isn't |
140 | #define ALIGNED_ALLOC_AVAILABLE() (true) |
141 | #endif |
142 | |
143 | TEST(TestRtsanInterceptors, AlignedAllocDiesWhenRealtime) { |
144 | if (ALIGNED_ALLOC_AVAILABLE()) { |
145 | auto Func = []() { EXPECT_NE(nullptr, aligned_alloc(alignment: 16, size: 32)); }; |
146 | ExpectRealtimeDeath(Func, intercepted_method_name: "aligned_alloc" ); |
147 | ExpectNonRealtimeSurvival(Func); |
148 | } |
149 | } |
150 | |
151 | // free_sized and free_aligned_sized (both C23) are not yet supported |
152 | TEST(TestRtsanInterceptors, FreeDiesWhenRealtime) { |
153 | void *ptr_1 = malloc(size: 1); |
154 | void *ptr_2 = malloc(size: 1); |
155 | ExpectRealtimeDeath(Func: [ptr_1]() { free(ptr: ptr_1); }, intercepted_method_name: "free" ); |
156 | ExpectNonRealtimeSurvival(Func: [ptr_2]() { free(ptr: ptr_2); }); |
157 | |
158 | // Prevent malloc/free pair being optimised out |
159 | ASSERT_NE(nullptr, ptr_1); |
160 | ASSERT_NE(nullptr, ptr_2); |
161 | } |
162 | |
163 | TEST(TestRtsanInterceptors, FreeSurvivesWhenRealtimeIfArgumentIsNull) { |
164 | RealtimeInvoke(Func: []() { free(NULL); }); |
165 | ExpectNonRealtimeSurvival(Func: []() { free(NULL); }); |
166 | } |
167 | |
168 | TEST(TestRtsanInterceptors, PosixMemalignDiesWhenRealtime) { |
169 | auto Func = []() { |
170 | void *ptr; |
171 | posix_memalign(memptr: &ptr, alignment: 4, size: 4); |
172 | }; |
173 | ExpectRealtimeDeath(Func, intercepted_method_name: "posix_memalign" ); |
174 | ExpectNonRealtimeSurvival(Func); |
175 | } |
176 | |
177 | #if SANITIZER_INTERCEPT_MEMALIGN |
178 | TEST(TestRtsanInterceptors, MemalignDiesWhenRealtime) { |
179 | auto Func = []() { EXPECT_NE(memalign(alignment: 2, size: 2048), nullptr); }; |
180 | ExpectRealtimeDeath(Func, intercepted_method_name: "memalign" ); |
181 | ExpectNonRealtimeSurvival(Func); |
182 | } |
183 | #endif |
184 | |
185 | #if SANITIZER_INTERCEPT_PVALLOC |
186 | TEST(TestRtsanInterceptors, PvallocDiesWhenRealtime) { |
187 | auto Func = []() { EXPECT_NE(pvalloc(size: 2048), nullptr); }; |
188 | ExpectRealtimeDeath(Func, intercepted_method_name: "pvalloc" ); |
189 | ExpectNonRealtimeSurvival(Func); |
190 | } |
191 | #endif |
192 | |
193 | TEST(TestRtsanInterceptors, MmapDiesWhenRealtime) { |
194 | auto Func = []() { |
195 | void *_ = mmap(addr: nullptr, len: 8, PROT_READ | PROT_WRITE, |
196 | MAP_PRIVATE | MAP_ANONYMOUS, fd: -1, offset: 0); |
197 | }; |
198 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("mmap" )); |
199 | ExpectNonRealtimeSurvival(Func); |
200 | } |
201 | |
202 | #if SANITIZER_LINUX |
203 | TEST(TestRtsanInterceptors, MremapDiesWhenRealtime) { |
204 | void *addr = mmap(addr: nullptr, len: 8, PROT_READ | PROT_WRITE, |
205 | MAP_PRIVATE | MAP_ANONYMOUS, fd: -1, offset: 0); |
206 | auto Func = [addr]() { void *_ = mremap(addr: addr, old_len: 8, new_len: 16, flags: 0); }; |
207 | ExpectRealtimeDeath(Func, intercepted_method_name: "mremap" ); |
208 | ExpectNonRealtimeSurvival(Func); |
209 | } |
210 | #endif |
211 | |
212 | TEST(TestRtsanInterceptors, MunmapDiesWhenRealtime) { |
213 | void *ptr = mmap(addr: nullptr, len: 8, PROT_READ | PROT_WRITE, |
214 | MAP_PRIVATE | MAP_ANONYMOUS, fd: -1, offset: 0); |
215 | EXPECT_NE(ptr, nullptr); |
216 | auto Func = [ptr]() { munmap(addr: ptr, len: 8); }; |
217 | printf(format: "Right before death munmap\n" ); |
218 | ExpectRealtimeDeath(Func, intercepted_method_name: "munmap" ); |
219 | ExpectNonRealtimeSurvival(Func); |
220 | } |
221 | |
222 | class RtsanOpenedMmapTest : public RtsanFileTest { |
223 | protected: |
224 | void SetUp() override { |
225 | RtsanFileTest::SetUp(); |
226 | file = fopen(filename: GetTemporaryFilePath(), modes: "w+" ); |
227 | ASSERT_THAT(file, Ne(nullptr)); |
228 | fd = fileno(stream: file); |
229 | ASSERT_THAT(fd, Ne(-1)); |
230 | int ret = ftruncate(GetOpenFd(), size); |
231 | ASSERT_THAT(ret, Ne(-1)); |
232 | addr = |
233 | mmap(addr: nullptr, len: size, PROT_READ | PROT_WRITE, MAP_SHARED, fd: GetOpenFd(), offset: 0); |
234 | ASSERT_THAT(addr, Ne(MAP_FAILED)); |
235 | ASSERT_THAT(addr, Ne(nullptr)); |
236 | } |
237 | |
238 | void TearDown() override { |
239 | if (addr != nullptr && addr != MAP_FAILED) |
240 | munmap(addr: addr, len: size); |
241 | RtsanFileTest::TearDown(); |
242 | } |
243 | |
244 | void *GetAddr() { return addr; } |
245 | static constexpr size_t GetSize() { return size; } |
246 | |
247 | int GetOpenFd() { return fd; } |
248 | |
249 | private: |
250 | void *addr = nullptr; |
251 | static constexpr size_t size = 4096; |
252 | FILE *file = nullptr; |
253 | int fd = -1; |
254 | }; |
255 | |
256 | #if !SANITIZER_APPLE |
257 | TEST_F(RtsanOpenedMmapTest, MadviseDiesWhenRealtime) { |
258 | auto Func = [this]() { madvise(GetAddr(), GetSize(), MADV_NORMAL); }; |
259 | ExpectRealtimeDeath(Func, intercepted_method_name: "madvise" ); |
260 | ExpectNonRealtimeSurvival(Func); |
261 | } |
262 | |
263 | TEST_F(RtsanOpenedMmapTest, PosixMadviseDiesWhenRealtime) { |
264 | auto Func = [this]() { |
265 | posix_madvise(GetAddr(), GetSize(), POSIX_MADV_NORMAL); |
266 | }; |
267 | ExpectRealtimeDeath(Func, intercepted_method_name: "posix_madvise" ); |
268 | ExpectNonRealtimeSurvival(Func); |
269 | } |
270 | #endif |
271 | |
272 | TEST_F(RtsanOpenedMmapTest, MprotectDiesWhenRealtime) { |
273 | auto Func = [this]() { mprotect(GetAddr(), GetSize(), PROT_READ); }; |
274 | ExpectRealtimeDeath(Func, intercepted_method_name: "mprotect" ); |
275 | ExpectNonRealtimeSurvival(Func); |
276 | } |
277 | |
278 | TEST_F(RtsanOpenedMmapTest, MsyncDiesWhenRealtime) { |
279 | auto Func = [this]() { msync(GetAddr(), GetSize(), MS_INVALIDATE); }; |
280 | ExpectRealtimeDeath(Func, intercepted_method_name: "msync" ); |
281 | ExpectNonRealtimeSurvival(Func); |
282 | } |
283 | |
284 | TEST_F(RtsanOpenedMmapTest, MincoreDiesWhenRealtime) { |
285 | #if SANITIZER_APPLE |
286 | std::vector<char> vec(GetSize() / 1024); |
287 | #else |
288 | std::vector<unsigned char> vec(GetSize() / 1024); |
289 | #endif |
290 | auto Func = [this, &vec]() { mincore(GetAddr(), GetSize(), vec.data()); }; |
291 | ExpectRealtimeDeath(Func, intercepted_method_name: "mincore" ); |
292 | ExpectNonRealtimeSurvival(Func); |
293 | } |
294 | |
295 | TEST(TestRtsanInterceptors, ShmOpenDiesWhenRealtime) { |
296 | auto Func = []() { shm_open(name: "/rtsan_test_shm" , O_CREAT | O_RDWR, mode: 0); }; |
297 | ExpectRealtimeDeath(Func, intercepted_method_name: "shm_open" ); |
298 | ExpectNonRealtimeSurvival(Func); |
299 | } |
300 | |
301 | TEST(TestRtsanInterceptors, ShmUnlinkDiesWhenRealtime) { |
302 | auto Func = []() { shm_unlink(name: "/rtsan_test_shm" ); }; |
303 | ExpectRealtimeDeath(Func, intercepted_method_name: "shm_unlink" ); |
304 | ExpectNonRealtimeSurvival(Func); |
305 | } |
306 | |
307 | #if !SANITIZER_APPLE |
308 | TEST(TestRtsanInterceptors, MemfdCreateDiesWhenRealtime) { |
309 | auto Func = []() { memfd_create(name: "/rtsan_test_memfd_create" , MFD_CLOEXEC); }; |
310 | ExpectRealtimeDeath(Func, intercepted_method_name: "memfd_create" ); |
311 | ExpectNonRealtimeSurvival(Func); |
312 | } |
313 | #endif |
314 | |
315 | /* |
316 | Sleeping |
317 | */ |
318 | |
319 | TEST(TestRtsanInterceptors, SleepDiesWhenRealtime) { |
320 | auto Func = []() { sleep(0u); }; |
321 | ExpectRealtimeDeath(Func, intercepted_method_name: "sleep" ); |
322 | ExpectNonRealtimeSurvival(Func); |
323 | } |
324 | |
325 | TEST(TestRtsanInterceptors, UsleepDiesWhenRealtime) { |
326 | auto Func = []() { usleep(1u); }; |
327 | ExpectRealtimeDeath(Func, intercepted_method_name: "usleep" ); |
328 | ExpectNonRealtimeSurvival(Func); |
329 | } |
330 | |
331 | TEST(TestRtsanInterceptors, NanosleepDiesWhenRealtime) { |
332 | auto Func = []() { |
333 | timespec T{}; |
334 | nanosleep(requested_time: &T, remaining: &T); |
335 | }; |
336 | ExpectRealtimeDeath(Func, intercepted_method_name: "nanosleep" ); |
337 | ExpectNonRealtimeSurvival(Func); |
338 | } |
339 | |
340 | TEST(TestRtsanInterceptors, SchedYieldDiesWhenRealtime) { |
341 | auto Func = []() { sched_yield(); }; |
342 | ExpectRealtimeDeath(Func, intercepted_method_name: "sched_yield" ); |
343 | ExpectNonRealtimeSurvival(Func); |
344 | } |
345 | |
346 | #if SANITIZER_LINUX |
347 | TEST(TestRtsanInterceptors, SchedGetaffinityDiesWhenRealtime) { |
348 | cpu_set_t set{}; |
349 | auto Func = [&set]() { sched_getaffinity(pid: 0, cpusetsize: sizeof(set), cpuset: &set); }; |
350 | ExpectRealtimeDeath(Func, intercepted_method_name: "sched_getaffinity" ); |
351 | ExpectNonRealtimeSurvival(Func); |
352 | } |
353 | |
354 | TEST(TestRtsanInterceptors, SchedSetaffinityDiesWhenRealtime) { |
355 | cpu_set_t set{}; |
356 | auto Func = [&set]() { sched_setaffinity(pid: 0, cpusetsize: sizeof(set), cpuset: &set); }; |
357 | ExpectRealtimeDeath(Func, intercepted_method_name: "sched_setaffinity" ); |
358 | ExpectNonRealtimeSurvival(Func); |
359 | } |
360 | #endif |
361 | |
362 | /* |
363 | Filesystem |
364 | */ |
365 | |
366 | TEST_F(RtsanFileTest, OpenDiesWhenRealtime) { |
367 | auto Func = [this]() { open(GetTemporaryFilePath(), O_RDONLY); }; |
368 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("open" )); |
369 | ExpectNonRealtimeSurvival(Func); |
370 | } |
371 | |
372 | TEST_F(RtsanFileTest, OpenatDiesWhenRealtime) { |
373 | auto Func = [this]() { openat(0, GetTemporaryFilePath(), O_RDONLY); }; |
374 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("openat" )); |
375 | ExpectNonRealtimeSurvival(Func); |
376 | } |
377 | |
378 | TEST_F(RtsanFileTest, OpenCreatesFileWithProperMode) { |
379 | const mode_t existing_umask = umask(mask: 0); |
380 | umask(mask: existing_umask); |
381 | |
382 | const int mode = S_IRGRP | S_IROTH | S_IRUSR | S_IWUSR; |
383 | |
384 | const int fd = open(GetTemporaryFilePath(), O_CREAT | O_WRONLY, mode); |
385 | ASSERT_THAT(fd, Ne(-1)); |
386 | close(fd); |
387 | |
388 | struct stat st; |
389 | ASSERT_THAT(stat(GetTemporaryFilePath(), &st), Eq(0)); |
390 | |
391 | // Mask st_mode to get permission bits only |
392 | const mode_t actual_mode = st.st_mode & 0777; |
393 | const mode_t expected_mode = mode & ~existing_umask; |
394 | ASSERT_THAT(actual_mode, Eq(expected_mode)); |
395 | } |
396 | |
397 | TEST_F(RtsanFileTest, CreatDiesWhenRealtime) { |
398 | auto Func = [this]() { creat(GetTemporaryFilePath(), S_IWOTH | S_IROTH); }; |
399 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("creat" )); |
400 | ExpectNonRealtimeSurvival(Func); |
401 | } |
402 | |
403 | TEST(TestRtsanInterceptors, FcntlDiesWhenRealtime) { |
404 | auto Func = []() { fcntl(fd: 0, F_GETFL); }; |
405 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fcntl" )); |
406 | ExpectNonRealtimeSurvival(Func); |
407 | } |
408 | |
409 | TEST_F(RtsanFileTest, FcntlFlockDiesWhenRealtime) { |
410 | int fd = creat(GetTemporaryFilePath(), S_IRUSR | S_IWUSR); |
411 | ASSERT_THAT(fd, Ne(-1)); |
412 | |
413 | auto Func = [fd]() { |
414 | struct flock lock{}; |
415 | lock.l_type = F_RDLCK; |
416 | lock.l_whence = SEEK_SET; |
417 | lock.l_start = 0; |
418 | lock.l_len = 0; |
419 | lock.l_pid = ::getpid(); |
420 | |
421 | ASSERT_THAT(fcntl(fd: fd, F_GETLK, &lock), Eq(0)); |
422 | ASSERT_THAT(lock.l_type, F_UNLCK); |
423 | }; |
424 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fcntl" )); |
425 | ExpectNonRealtimeSurvival(Func); |
426 | |
427 | close(fd); |
428 | } |
429 | |
430 | TEST_F(RtsanFileTest, FcntlSetFdDiesWhenRealtime) { |
431 | int fd = creat(GetTemporaryFilePath(), S_IRUSR | S_IWUSR); |
432 | ASSERT_THAT(fd, Ne(-1)); |
433 | |
434 | auto Func = [fd]() { |
435 | int old_flags = fcntl(fd: fd, F_GETFD); |
436 | ASSERT_THAT(fcntl(fd: fd, F_SETFD, FD_CLOEXEC), Eq(0)); |
437 | |
438 | int flags = fcntl(fd: fd, F_GETFD); |
439 | ASSERT_THAT(flags, Ne(-1)); |
440 | ASSERT_THAT(flags & FD_CLOEXEC, Eq(FD_CLOEXEC)); |
441 | |
442 | ASSERT_THAT(fcntl(fd: fd, F_SETFD, old_flags), Eq(0)); |
443 | ASSERT_THAT(fcntl(fd: fd, F_GETFD), Eq(old_flags)); |
444 | }; |
445 | |
446 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fcntl" )); |
447 | ExpectNonRealtimeSurvival(Func); |
448 | |
449 | close(fd); |
450 | } |
451 | |
452 | TEST(TestRtsanInterceptors, CloseDiesWhenRealtime) { |
453 | auto Func = []() { close(0); }; |
454 | ExpectRealtimeDeath(Func, intercepted_method_name: "close" ); |
455 | ExpectNonRealtimeSurvival(Func); |
456 | } |
457 | |
458 | TEST(TestRtsanInterceptors, ChdirDiesWhenRealtime) { |
459 | auto Func = []() { chdir("." ); }; |
460 | ExpectRealtimeDeath(Func, intercepted_method_name: "chdir" ); |
461 | ExpectNonRealtimeSurvival(Func); |
462 | } |
463 | |
464 | TEST(TestRtsanInterceptors, FchdirDiesWhenRealtime) { |
465 | auto Func = []() { fchdir(0); }; |
466 | ExpectRealtimeDeath(Func, intercepted_method_name: "fchdir" ); |
467 | ExpectNonRealtimeSurvival(Func); |
468 | } |
469 | |
470 | #if SANITIZER_INTERCEPT_READLINK |
471 | TEST(TestRtsanInterceptors, ReadlinkDiesWhenRealtime) { |
472 | char buf[1024]; |
473 | auto Func = [&buf]() { readlink("/proc/self" , buf, sizeof(buf)); }; |
474 | ExpectRealtimeDeath(Func, intercepted_method_name: "readlink" ); |
475 | ExpectNonRealtimeSurvival(Func); |
476 | } |
477 | #endif |
478 | |
479 | #if SANITIZER_INTERCEPT_READLINKAT |
480 | TEST(TestRtsanInterceptors, ReadlinkatDiesWhenRealtime) { |
481 | char buf[1024]; |
482 | auto Func = [&buf]() { readlinkat(0, "/proc/self" , buf, sizeof(buf)); }; |
483 | ExpectRealtimeDeath(Func, intercepted_method_name: "readlinkat" ); |
484 | ExpectNonRealtimeSurvival(Func); |
485 | } |
486 | #endif |
487 | |
488 | TEST_F(RtsanFileTest, FopenDiesWhenRealtime) { |
489 | auto Func = [this]() { |
490 | FILE *f = fopen(GetTemporaryFilePath(), "w" ); |
491 | EXPECT_THAT(f, Ne(nullptr)); |
492 | }; |
493 | |
494 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fopen" )); |
495 | ExpectNonRealtimeSurvival(Func); |
496 | } |
497 | |
498 | #if SANITIZER_INTERCEPT_FOPENCOOKIE |
499 | TEST_F(RtsanFileTest, FopenCookieDieWhenRealtime) { |
500 | FILE *f = fopen(GetTemporaryFilePath(), "w" ); |
501 | EXPECT_THAT(f, Ne(nullptr)); |
502 | struct fholder { |
503 | FILE *fp; |
504 | size_t read; |
505 | } fh = {.fp: f, .read: 0}; |
506 | auto CookieRead = [](void *cookie, char *buf, size_t size) { |
507 | fholder *p = reinterpret_cast<fholder *>(cookie); |
508 | p->read = fread(ptr: static_cast<void *>(buf), size: 1, n: size, stream: p->fp); |
509 | EXPECT_NE(0u, p->read); |
510 | }; |
511 | cookie_io_functions_t funcs = {.read: (cookie_read_function_t *)&CookieRead, .write: nullptr, |
512 | .seek: nullptr, .close: nullptr}; |
513 | auto Func = [&fh, &funcs]() { |
514 | FILE *f = fopencookie(magic_cookie: &fh, modes: "w" , io_funcs: funcs); |
515 | EXPECT_THAT(f, Ne(nullptr)); |
516 | }; |
517 | |
518 | ExpectRealtimeDeath(Func, intercepted_method_name: "fopencookie" ); |
519 | ExpectNonRealtimeSurvival(Func); |
520 | } |
521 | #endif |
522 | |
523 | #if SANITIZER_INTERCEPT_OPEN_MEMSTREAM |
524 | TEST_F(RtsanFileTest, OpenMemstreamDiesWhenRealtime) { |
525 | char *buffer; |
526 | size_t size; |
527 | auto Func = [&buffer, &size]() { |
528 | FILE *f = open_memstream(bufloc: &buffer, sizeloc: &size); |
529 | EXPECT_THAT(f, Ne(nullptr)); |
530 | }; |
531 | |
532 | ExpectRealtimeDeath(Func, intercepted_method_name: "open_memstream" ); |
533 | ExpectNonRealtimeSurvival(Func); |
534 | } |
535 | |
536 | TEST_F(RtsanFileTest, FmemOpenDiesWhenRealtime) { |
537 | char buffer[1024]; |
538 | auto Func = [&buffer]() { |
539 | FILE *f = fmemopen(s: &buffer, len: sizeof(buffer), modes: "w" ); |
540 | EXPECT_THAT(f, Ne(nullptr)); |
541 | }; |
542 | |
543 | ExpectRealtimeDeath(Func, intercepted_method_name: "fmemopen" ); |
544 | ExpectNonRealtimeSurvival(Func); |
545 | } |
546 | #endif |
547 | |
548 | #if SANITIZER_INTERCEPT_SETVBUF |
549 | TEST_F(RtsanFileTest, SetbufDieWhenRealtime) { |
550 | char buffer[BUFSIZ]; |
551 | FILE *f = fopen(GetTemporaryFilePath(), "w" ); |
552 | EXPECT_THAT(f, Ne(nullptr)); |
553 | |
554 | auto Func = [f, &buffer]() { setbuf(stream: f, buf: buffer); }; |
555 | |
556 | ExpectRealtimeDeath(Func, intercepted_method_name: "setbuf" ); |
557 | ExpectNonRealtimeSurvival(Func); |
558 | } |
559 | |
560 | TEST_F(RtsanFileTest, SetvbufDieWhenRealtime) { |
561 | char buffer[1024]; |
562 | size_t size = sizeof(buffer); |
563 | FILE *f = fopen(GetTemporaryFilePath(), "w" ); |
564 | EXPECT_THAT(f, Ne(nullptr)); |
565 | |
566 | auto Func = [f, &buffer, size]() { |
567 | int r = setvbuf(stream: f, buf: buffer, _IOFBF, n: size); |
568 | EXPECT_THAT(r, Eq(0)); |
569 | }; |
570 | |
571 | ExpectRealtimeDeath(Func, intercepted_method_name: "setvbuf" ); |
572 | ExpectNonRealtimeSurvival(Func); |
573 | } |
574 | |
575 | TEST_F(RtsanFileTest, SetlinebufDieWhenRealtime) { |
576 | FILE *f = fopen(GetTemporaryFilePath(), "w" ); |
577 | EXPECT_THAT(f, Ne(nullptr)); |
578 | |
579 | auto Func = [f]() { setlinebuf(f); }; |
580 | |
581 | ExpectRealtimeDeath(Func, intercepted_method_name: "setlinebuf" ); |
582 | ExpectNonRealtimeSurvival(Func); |
583 | } |
584 | |
585 | TEST_F(RtsanFileTest, SetbufferDieWhenRealtime) { |
586 | char buffer[1024]; |
587 | size_t size = sizeof(buffer); |
588 | FILE *f = fopen(GetTemporaryFilePath(), "w" ); |
589 | EXPECT_THAT(f, Ne(nullptr)); |
590 | |
591 | auto Func = [f, &buffer, size]() { setbuffer(stream: f, buf: buffer, size: size); }; |
592 | |
593 | ExpectRealtimeDeath(Func, intercepted_method_name: "setbuffer" ); |
594 | ExpectNonRealtimeSurvival(Func); |
595 | } |
596 | #endif |
597 | |
598 | class RtsanOpenedFileTest : public RtsanFileTest { |
599 | protected: |
600 | void SetUp() override { |
601 | RtsanFileTest::SetUp(); |
602 | file = fopen(filename: GetTemporaryFilePath(), modes: "w" ); |
603 | ASSERT_THAT(file, Ne(nullptr)); |
604 | fd = fileno(stream: file); |
605 | ASSERT_THAT(fd, Ne(-1)); |
606 | } |
607 | |
608 | void TearDown() override { |
609 | if (file != nullptr) |
610 | fclose(stream: file); |
611 | RtsanFileTest::TearDown(); |
612 | } |
613 | |
614 | FILE *GetOpenFile() { return file; } |
615 | |
616 | int GetOpenFd() { return fd; } |
617 | |
618 | private: |
619 | FILE *file = nullptr; |
620 | int fd = -1; |
621 | }; |
622 | |
623 | #if SANITIZER_INTERCEPT_FSEEK |
624 | TEST_F(RtsanOpenedFileTest, FgetposDieWhenRealtime) { |
625 | auto Func = [this]() { |
626 | fpos_t pos; |
627 | int ret = fgetpos(GetOpenFile(), &pos); |
628 | ASSERT_THAT(ret, Eq(0)); |
629 | }; |
630 | |
631 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fgetpos" )); |
632 | ExpectNonRealtimeSurvival(Func); |
633 | } |
634 | |
635 | TEST_F(RtsanOpenedFileTest, FsetposDieWhenRealtime) { |
636 | fpos_t pos; |
637 | int ret = fgetpos(GetOpenFile(), &pos); |
638 | ASSERT_THAT(ret, Eq(0)); |
639 | auto Func = [this, pos]() { |
640 | int ret = fsetpos(GetOpenFile(), &pos); |
641 | ASSERT_THAT(ret, Eq(0)); |
642 | }; |
643 | |
644 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fsetpos" )); |
645 | ExpectNonRealtimeSurvival(Func); |
646 | } |
647 | |
648 | TEST_F(RtsanOpenedFileTest, FseekDieWhenRealtime) { |
649 | auto Func = [this]() { |
650 | int ret = fseek(GetOpenFile(), 0, SEEK_CUR); |
651 | ASSERT_THAT(ret, Eq(0)); |
652 | }; |
653 | |
654 | ExpectRealtimeDeath(Func, intercepted_method_name: "fseek" ); |
655 | ExpectNonRealtimeSurvival(Func); |
656 | } |
657 | |
658 | TEST_F(RtsanOpenedFileTest, FseekoDieWhenRealtime) { |
659 | auto Func = [this]() { |
660 | int ret = fseeko(GetOpenFile(), 0, SEEK_CUR); |
661 | ASSERT_THAT(ret, Eq(0)); |
662 | }; |
663 | |
664 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("fseeko" )); |
665 | ExpectNonRealtimeSurvival(Func); |
666 | } |
667 | |
668 | TEST_F(RtsanOpenedFileTest, FtellDieWhenRealtime) { |
669 | auto Func = [this]() { |
670 | long ret = ftell(GetOpenFile()); |
671 | ASSERT_THAT(ret, Eq(0)); |
672 | }; |
673 | |
674 | ExpectRealtimeDeath(Func, intercepted_method_name: "ftell" ); |
675 | ExpectNonRealtimeSurvival(Func); |
676 | } |
677 | |
678 | TEST_F(RtsanOpenedFileTest, FtelloDieWhenRealtime) { |
679 | auto Func = [this]() { |
680 | off_t ret = ftello(GetOpenFile()); |
681 | ASSERT_THAT(ret, Eq(0)); |
682 | }; |
683 | |
684 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("ftello" )); |
685 | ExpectNonRealtimeSurvival(Func); |
686 | } |
687 | |
688 | TEST_F(RtsanOpenedFileTest, RewindDieWhenRealtime) { |
689 | int end = fseek(GetOpenFile(), 0, SEEK_END); |
690 | EXPECT_THAT(end, Eq(0)); |
691 | auto Func = [this]() { rewind(GetOpenFile()); }; |
692 | |
693 | ExpectRealtimeDeath(Func, intercepted_method_name: "rewind" ); |
694 | ExpectNonRealtimeSurvival(Func); |
695 | } |
696 | #endif |
697 | |
698 | TEST(TestRtsanInterceptors, IoctlDiesWhenRealtime) { |
699 | auto Func = []() { ioctl(fd: 0, FIONREAD); }; |
700 | ExpectRealtimeDeath(Func, intercepted_method_name: "ioctl" ); |
701 | ExpectNonRealtimeSurvival(Func); |
702 | } |
703 | |
704 | TEST_F(RtsanOpenedFileTest, IoctlBehavesWithOutputArg) { |
705 | int arg{}; |
706 | ioctl(GetOpenFd(), FIONREAD, &arg); |
707 | |
708 | EXPECT_THAT(arg, Ge(0)); |
709 | } |
710 | |
711 | TEST_F(RtsanOpenedFileTest, FdopenDiesWhenRealtime) { |
712 | auto Func = [&]() { |
713 | FILE *f = fdopen(GetOpenFd(), "w" ); |
714 | EXPECT_THAT(f, Ne(nullptr)); |
715 | }; |
716 | |
717 | ExpectRealtimeDeath(Func, intercepted_method_name: "fdopen" ); |
718 | ExpectNonRealtimeSurvival(Func); |
719 | } |
720 | |
721 | TEST_F(RtsanOpenedFileTest, FreopenDiesWhenRealtime) { |
722 | auto Func = [&]() { |
723 | FILE *newfile = freopen(GetTemporaryFilePath(), "w" , GetOpenFile()); |
724 | EXPECT_THAT(newfile, Ne(nullptr)); |
725 | }; |
726 | |
727 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("freopen" )); |
728 | ExpectNonRealtimeSurvival(Func); |
729 | } |
730 | |
731 | TEST(TestRtsanInterceptors, IoctlBehavesWithOutputPointer) { |
732 | // These initial checks just see if we CAN run these tests. |
733 | // If we can't (can't open a socket, or can't find an interface, just |
734 | // gracefully skip. |
735 | int sock = socket(AF_INET, SOCK_STREAM, protocol: 0); |
736 | if (sock == -1) { |
737 | perror(s: "socket" ); |
738 | GTEST_SKIP(); |
739 | } |
740 | |
741 | struct ifaddrs *ifaddr = nullptr; |
742 | if (getifaddrs(ifap: &ifaddr) == -1 || ifaddr == nullptr) { |
743 | perror(s: "getifaddrs" ); |
744 | close(sock); |
745 | GTEST_SKIP(); |
746 | } |
747 | |
748 | struct ifreq ifr{}; |
749 | strncpy(ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ - 1); |
750 | |
751 | int retval = ioctl(fd: sock, SIOCGIFADDR, &ifr); |
752 | if (retval == -1) { |
753 | perror(s: "ioctl" ); |
754 | close(sock); |
755 | freeifaddrs(ifa: ifaddr); |
756 | FAIL(); |
757 | } |
758 | |
759 | freeifaddrs(ifa: ifaddr); |
760 | close(sock); |
761 | |
762 | ASSERT_THAT(ifr.ifr_addr.sa_data, NotNull()); |
763 | ASSERT_THAT(ifr.ifr_addr.sa_family, Eq(AF_INET)); |
764 | } |
765 | |
766 | TEST_F(RtsanOpenedFileTest, LseekDiesWhenRealtime) { |
767 | auto Func = [this]() { lseek(GetOpenFd(), 0, SEEK_SET); }; |
768 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("lseek" )); |
769 | ExpectNonRealtimeSurvival(Func); |
770 | } |
771 | |
772 | TEST_F(RtsanOpenedFileTest, DupDiesWhenRealtime) { |
773 | auto Func = [this]() { dup(GetOpenFd()); }; |
774 | ExpectRealtimeDeath(Func, intercepted_method_name: "dup" ); |
775 | ExpectNonRealtimeSurvival(Func); |
776 | } |
777 | |
778 | TEST_F(RtsanOpenedFileTest, Dup2DiesWhenRealtime) { |
779 | auto Func = [this]() { dup2(GetOpenFd(), 0); }; |
780 | ExpectRealtimeDeath(Func, intercepted_method_name: "dup2" ); |
781 | ExpectNonRealtimeSurvival(Func); |
782 | } |
783 | |
784 | TEST_F(RtsanFileTest, ChmodDiesWhenRealtime) { |
785 | auto Func = [this]() { chmod(GetTemporaryFilePath(), 0777); }; |
786 | ExpectRealtimeDeath(Func, intercepted_method_name: "chmod" ); |
787 | ExpectNonRealtimeSurvival(Func); |
788 | } |
789 | |
790 | TEST_F(RtsanOpenedFileTest, FchmodDiesWhenRealtime) { |
791 | auto Func = [this]() { fchmod(GetOpenFd(), 0777); }; |
792 | ExpectRealtimeDeath(Func, intercepted_method_name: "fchmod" ); |
793 | ExpectNonRealtimeSurvival(Func); |
794 | } |
795 | |
796 | TEST(TestRtsanInterceptors, UmaskDiesWhenRealtime) { |
797 | auto Func = []() { umask(mask: 0); }; |
798 | ExpectRealtimeDeath(Func, intercepted_method_name: "umask" ); |
799 | ExpectNonRealtimeSurvival(Func); |
800 | } |
801 | |
802 | #if SANITIZER_INTERCEPT_PROCESS_VM_READV |
803 | TEST(TestRtsanInterceptors, ProcessVmReadvDiesWhenRealtime) { |
804 | char stack[1024]; |
805 | int p; |
806 | iovec lcl{.iov_base: &stack, .iov_len: sizeof(stack)}; |
807 | iovec rmt{.iov_base: &p, .iov_len: sizeof(p)}; |
808 | auto Func = [&lcl, &rmt]() { process_vm_readv(pid: 0, lvec: &lcl, liovcnt: 1, rvec: &rmt, riovcnt: 1, flags: 0); }; |
809 | ExpectRealtimeDeath(Func, intercepted_method_name: "process_vm_readv" ); |
810 | ExpectNonRealtimeSurvival(Func); |
811 | } |
812 | |
813 | TEST(TestRtsanInterceptors, ProcessVmWritevDiesWhenRealtime) { |
814 | char stack[1024]; |
815 | int p; |
816 | iovec lcl{.iov_base: &p, .iov_len: sizeof(p)}; |
817 | iovec rmt{.iov_base: &stack, .iov_len: sizeof(stack)}; |
818 | auto Func = [&lcl, &rmt]() { process_vm_writev(pid: 0, lvec: &lcl, liovcnt: 1, rvec: &rmt, riovcnt: 1, flags: 0); }; |
819 | ExpectRealtimeDeath(Func, intercepted_method_name: "process_vm_writev" ); |
820 | ExpectNonRealtimeSurvival(Func); |
821 | } |
822 | #endif |
823 | |
824 | class RtsanDirectoryTest : public ::testing::Test { |
825 | protected: |
826 | void SetUp() override { |
827 | const ::testing::TestInfo *const test_info = |
828 | ::testing::UnitTest::GetInstance()->current_test_info(); |
829 | directory_path_ = std::string("/tmp/rtsan_temp_dir_" ) + test_info->name(); |
830 | RemoveTemporaryDirectory(); |
831 | } |
832 | |
833 | const char *GetTemporaryDirectoryPath() const { |
834 | return directory_path_.c_str(); |
835 | } |
836 | |
837 | void TearDown() override { RemoveTemporaryDirectory(); } |
838 | |
839 | private: |
840 | void RemoveTemporaryDirectory() const { |
841 | std::remove(filename: GetTemporaryDirectoryPath()); |
842 | } |
843 | std::string directory_path_; |
844 | }; |
845 | |
846 | TEST_F(RtsanDirectoryTest, MkdirDiesWhenRealtime) { |
847 | auto Func = [this]() { mkdir(GetTemporaryDirectoryPath(), 0777); }; |
848 | ExpectRealtimeDeath(Func, intercepted_method_name: "mkdir" ); |
849 | ExpectNonRealtimeSurvival(Func); |
850 | } |
851 | |
852 | TEST_F(RtsanDirectoryTest, RmdirDiesWhenRealtime) { |
853 | // We don't actually create this directory before we try to remove it |
854 | // Thats OK - we are just making sure the call gets intercepted |
855 | auto Func = [this]() { rmdir(GetTemporaryDirectoryPath()); }; |
856 | ExpectRealtimeDeath(Func, intercepted_method_name: "rmdir" ); |
857 | ExpectNonRealtimeSurvival(Func); |
858 | } |
859 | |
860 | TEST_F(RtsanOpenedFileTest, FreadDiesWhenRealtime) { |
861 | auto Func = [this]() { |
862 | char c{}; |
863 | fread(&c, 1, 1, GetOpenFile()); |
864 | }; |
865 | ExpectRealtimeDeath(Func, intercepted_method_name: "fread" ); |
866 | ExpectNonRealtimeSurvival(Func); |
867 | } |
868 | |
869 | TEST_F(RtsanOpenedFileTest, FwriteDiesWhenRealtime) { |
870 | const char *message = "Hello, world!" ; |
871 | auto Func = [&]() { fwrite(&message, 1, 4, GetOpenFile()); }; |
872 | ExpectRealtimeDeath(Func, intercepted_method_name: "fwrite" ); |
873 | ExpectNonRealtimeSurvival(Func); |
874 | } |
875 | |
876 | TEST_F(RtsanOpenedFileTest, UnlinkDiesWhenRealtime) { |
877 | auto Func = [&]() { unlink(GetTemporaryFilePath()); }; |
878 | ExpectRealtimeDeath(Func, intercepted_method_name: "unlink" ); |
879 | ExpectNonRealtimeSurvival(Func); |
880 | } |
881 | |
882 | TEST_F(RtsanOpenedFileTest, UnlinkatDiesWhenRealtime) { |
883 | auto Func = [&]() { unlinkat(0, GetTemporaryFilePath(), 0); }; |
884 | ExpectRealtimeDeath(Func, intercepted_method_name: "unlinkat" ); |
885 | ExpectNonRealtimeSurvival(Func); |
886 | } |
887 | |
888 | TEST_F(RtsanOpenedFileTest, TruncateDiesWhenRealtime) { |
889 | auto Func = [&]() { truncate(GetTemporaryFilePath(), 16); }; |
890 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("truncate" )); |
891 | ExpectNonRealtimeSurvival(Func); |
892 | } |
893 | |
894 | TEST_F(RtsanOpenedFileTest, FtruncateDiesWhenRealtime) { |
895 | auto Func = [&]() { ftruncate(GetOpenFd(), 16); }; |
896 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("ftruncate" )); |
897 | ExpectNonRealtimeSurvival(Func); |
898 | } |
899 | |
900 | TEST_F(RtsanOpenedFileTest, SymlinkDiesWhenRealtime) { |
901 | auto Func = [&]() { |
902 | symlink("/tmp/rtsan_symlink_test" , GetTemporaryFilePath()); |
903 | }; |
904 | ExpectRealtimeDeath(Func, intercepted_method_name: "symlink" ); |
905 | ExpectNonRealtimeSurvival(Func); |
906 | } |
907 | |
908 | TEST_F(RtsanOpenedFileTest, SymlinkatDiesWhenRealtime) { |
909 | auto Func = [&]() { |
910 | symlinkat("/tmp/rtsan_symlinkat_test" , AT_FDCWD, GetTemporaryFilePath()); |
911 | }; |
912 | ExpectRealtimeDeath(Func, intercepted_method_name: "symlinkat" ); |
913 | ExpectNonRealtimeSurvival(Func); |
914 | } |
915 | |
916 | TEST_F(RtsanFileTest, FcloseDiesWhenRealtime) { |
917 | FILE *f = fopen(GetTemporaryFilePath(), "w" ); |
918 | EXPECT_THAT(f, Ne(nullptr)); |
919 | auto Func = [f]() { fclose(stream: f); }; |
920 | ExpectRealtimeDeath(Func, intercepted_method_name: "fclose" ); |
921 | ExpectNonRealtimeSurvival(Func); |
922 | } |
923 | |
924 | TEST(TestRtsanInterceptors, PutsDiesWhenRealtime) { |
925 | auto Func = []() { puts(s: "Hello, world!\n" ); }; |
926 | ExpectRealtimeDeath(Func); |
927 | ExpectNonRealtimeSurvival(Func); |
928 | } |
929 | |
930 | TEST_F(RtsanOpenedFileTest, FputsDiesWhenRealtime) { |
931 | auto Func = [this]() { fputs("Hello, world!\n" , GetOpenFile()); }; |
932 | ExpectRealtimeDeath(Func); |
933 | ExpectNonRealtimeSurvival(Func); |
934 | } |
935 | |
936 | TEST_F(RtsanFileTest, FflushDiesWhenRealtime) { |
937 | FILE *f = fopen(GetTemporaryFilePath(), "w" ); |
938 | EXPECT_THAT(f, Ne(nullptr)); |
939 | int written = fwrite(ptr: "abc" , size: 1, n: 3, s: f); |
940 | EXPECT_THAT(written, Eq(3)); |
941 | auto Func = [&f]() { |
942 | int res = fflush(stream: f); |
943 | EXPECT_THAT(res, Eq(0)); |
944 | }; |
945 | ExpectRealtimeDeath(Func, intercepted_method_name: "fflush" ); |
946 | ExpectNonRealtimeSurvival(Func); |
947 | } |
948 | |
949 | #if SANITIZER_APPLE |
950 | TEST_F(RtsanFileTest, FpurgeDiesWhenRealtime) { |
951 | FILE *f = fopen(GetTemporaryFilePath(), "w" ); |
952 | EXPECT_THAT(f, Ne(nullptr)); |
953 | int written = fwrite("abc" , 1, 3, f); |
954 | EXPECT_THAT(written, Eq(3)); |
955 | auto Func = [&f]() { |
956 | int res = fpurge(f); |
957 | EXPECT_THAT(res, Eq(0)); |
958 | }; |
959 | ExpectRealtimeDeath(Func, "fpurge" ); |
960 | ExpectNonRealtimeSurvival(Func); |
961 | } |
962 | #endif |
963 | |
964 | TEST_F(RtsanOpenedFileTest, ReadDiesWhenRealtime) { |
965 | auto Func = [this]() { |
966 | char c{}; |
967 | read(GetOpenFd(), &c, 1); |
968 | }; |
969 | ExpectRealtimeDeath(Func, intercepted_method_name: "read" ); |
970 | ExpectNonRealtimeSurvival(Func); |
971 | } |
972 | |
973 | TEST_F(RtsanOpenedFileTest, WriteDiesWhenRealtime) { |
974 | auto Func = [this]() { |
975 | char c = 'a'; |
976 | write(GetOpenFd(), &c, 1); |
977 | }; |
978 | ExpectRealtimeDeath(Func, intercepted_method_name: "write" ); |
979 | ExpectNonRealtimeSurvival(Func); |
980 | } |
981 | |
982 | TEST_F(RtsanOpenedFileTest, PreadDiesWhenRealtime) { |
983 | auto Func = [this]() { |
984 | char c{}; |
985 | pread(GetOpenFd(), &c, 1, 0); |
986 | }; |
987 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("pread" )); |
988 | ExpectNonRealtimeSurvival(Func); |
989 | } |
990 | |
991 | #if SANITIZER_INTERCEPT_PREADV |
992 | TEST_F(RtsanOpenedFileTest, PreadvDiesWhenRealtime) { |
993 | auto Func = [this]() { |
994 | char c{}; |
995 | iovec iov{.iov_base: &c, .iov_len: sizeof(c)}; |
996 | preadv(GetOpenFd(), &iov, 1, 0); |
997 | }; |
998 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("preadv" )); |
999 | ExpectNonRealtimeSurvival(Func); |
1000 | } |
1001 | #endif |
1002 | |
1003 | #if SANITIZER_INTERCEPT_PWRITEV |
1004 | TEST_F(RtsanOpenedFileTest, PwritevDiesWhenRealtime) { |
1005 | auto Func = [this]() { |
1006 | char c{}; |
1007 | iovec iov{.iov_base: &c, .iov_len: sizeof(c)}; |
1008 | pwritev(GetOpenFd(), &iov, 1, 0); |
1009 | }; |
1010 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("pwritev" )); |
1011 | ExpectNonRealtimeSurvival(Func); |
1012 | } |
1013 | #endif |
1014 | |
1015 | TEST_F(RtsanOpenedFileTest, ReadvDiesWhenRealtime) { |
1016 | auto Func = [this]() { |
1017 | char c{}; |
1018 | iovec iov{.iov_base: &c, .iov_len: 1}; |
1019 | readv(GetOpenFd(), &iov, 1); |
1020 | }; |
1021 | ExpectRealtimeDeath(Func, intercepted_method_name: "readv" ); |
1022 | ExpectNonRealtimeSurvival(Func); |
1023 | } |
1024 | |
1025 | TEST_F(RtsanOpenedFileTest, PwriteDiesWhenRealtime) { |
1026 | auto Func = [this]() { |
1027 | char c = 'a'; |
1028 | pwrite(GetOpenFd(), &c, 1, 0); |
1029 | }; |
1030 | ExpectRealtimeDeath(Func, MAYBE_APPEND_64("pwrite" )); |
1031 | ExpectNonRealtimeSurvival(Func); |
1032 | } |
1033 | |
1034 | TEST_F(RtsanOpenedFileTest, WritevDiesWhenRealtime) { |
1035 | auto Func = [this]() { |
1036 | char c = 'a'; |
1037 | iovec iov{.iov_base: &c, .iov_len: 1}; |
1038 | writev(GetOpenFd(), &iov, 1); |
1039 | }; |
1040 | ExpectRealtimeDeath(Func, intercepted_method_name: "writev" ); |
1041 | ExpectNonRealtimeSurvival(Func); |
1042 | } |
1043 | |
1044 | /* |
1045 | Concurrency |
1046 | */ |
1047 | |
1048 | TEST(TestRtsanInterceptors, PthreadCreateDiesWhenRealtime) { |
1049 | auto Func = []() { |
1050 | pthread_t thread{}; |
1051 | const pthread_attr_t attr{}; |
1052 | struct thread_info *thread_info{}; |
1053 | pthread_create(newthread: &thread, attr: &attr, start_routine: &FakeThreadEntryPoint, arg: thread_info); |
1054 | }; |
1055 | ExpectRealtimeDeath(Func, intercepted_method_name: "pthread_create" ); |
1056 | ExpectNonRealtimeSurvival(Func); |
1057 | } |
1058 | |
1059 | class PthreadMutexLockTest : public ::testing::Test { |
1060 | protected: |
1061 | void SetUp() override { |
1062 | pthread_mutex_init(mutex: &mutex, mutexattr: nullptr); |
1063 | is_locked = false; |
1064 | } |
1065 | |
1066 | void TearDown() override { |
1067 | if (is_locked) |
1068 | Unlock(); |
1069 | |
1070 | pthread_mutex_destroy(mutex: &mutex); |
1071 | } |
1072 | |
1073 | void Lock() { |
1074 | ASSERT_TRUE(!is_locked); |
1075 | pthread_mutex_lock(mutex: &mutex); |
1076 | is_locked = true; |
1077 | } |
1078 | |
1079 | void Unlock() { |
1080 | ASSERT_TRUE(is_locked); |
1081 | pthread_mutex_unlock(mutex: &mutex); |
1082 | is_locked = false; |
1083 | } |
1084 | |
1085 | private: |
1086 | pthread_mutex_t mutex; |
1087 | bool is_locked; |
1088 | }; |
1089 | |
1090 | TEST_F(PthreadMutexLockTest, PthreadMutexLockDiesWhenRealtime) { |
1091 | auto Func = [this]() { Lock(); }; |
1092 | |
1093 | ExpectRealtimeDeath(Func, intercepted_method_name: "pthread_mutex_lock" ); |
1094 | } |
1095 | |
1096 | TEST_F(PthreadMutexLockTest, PthreadMutexLockSurvivesWhenNotRealtime) { |
1097 | auto Func = [this]() { Lock(); }; |
1098 | |
1099 | ExpectNonRealtimeSurvival(Func); |
1100 | } |
1101 | |
1102 | TEST_F(PthreadMutexLockTest, PthreadMutexUnlockDiesWhenRealtime) { |
1103 | Lock(); |
1104 | auto Func = [this]() { Unlock(); }; |
1105 | |
1106 | ExpectRealtimeDeath(Func, intercepted_method_name: "pthread_mutex_unlock" ); |
1107 | ExpectNonRealtimeSurvival(Func); |
1108 | } |
1109 | |
1110 | TEST_F(PthreadMutexLockTest, PthreadMutexUnlockSurvivesWhenNotRealtime) { |
1111 | Lock(); |
1112 | auto Func = [this]() { Unlock(); }; |
1113 | |
1114 | ExpectNonRealtimeSurvival(Func); |
1115 | } |
1116 | |
1117 | TEST(TestRtsanInterceptors, PthreadJoinDiesWhenRealtime) { |
1118 | pthread_t thread{}; |
1119 | ASSERT_EQ(0, |
1120 | pthread_create(newthread: &thread, attr: nullptr, start_routine: &FakeThreadEntryPoint, arg: nullptr)); |
1121 | |
1122 | auto Func = [&thread]() { pthread_join(th: thread, thread_return: nullptr); }; |
1123 | |
1124 | ExpectRealtimeDeath(Func, intercepted_method_name: "pthread_join" ); |
1125 | ExpectNonRealtimeSurvival(Func); |
1126 | } |
1127 | |
1128 | #if SANITIZER_APPLE |
1129 | #pragma clang diagnostic push |
1130 | // OSSpinLockLock is deprecated, but still in use in libc++ |
1131 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
1132 | #undef OSSpinLockLock |
1133 | extern "C" { |
1134 | typedef int32_t OSSpinLock; |
1135 | void OSSpinLockLock(volatile OSSpinLock *__lock); |
1136 | // _os_nospin_lock_lock may replace OSSpinLockLock due to deprecation macro. |
1137 | typedef volatile OSSpinLock *_os_nospin_lock_t; |
1138 | void _os_nospin_lock_lock(_os_nospin_lock_t lock); |
1139 | } |
1140 | |
1141 | TEST(TestRtsanInterceptors, OsSpinLockLockDiesWhenRealtime) { |
1142 | auto Func = []() { |
1143 | OSSpinLock spin_lock{}; |
1144 | OSSpinLockLock(&spin_lock); |
1145 | }; |
1146 | ExpectRealtimeDeath(Func, "OSSpinLockLock" ); |
1147 | ExpectNonRealtimeSurvival(Func); |
1148 | } |
1149 | |
1150 | TEST(TestRtsanInterceptors, OsNoSpinLockLockDiesWhenRealtime) { |
1151 | OSSpinLock lock{}; |
1152 | auto Func = [&]() { _os_nospin_lock_lock(&lock); }; |
1153 | ExpectRealtimeDeath(Func, "_os_nospin_lock_lock" ); |
1154 | ExpectNonRealtimeSurvival(Func); |
1155 | } |
1156 | #pragma clang diagnostic pop //"-Wdeprecated-declarations" |
1157 | |
1158 | TEST(TestRtsanInterceptors, OsUnfairLockLockDiesWhenRealtime) { |
1159 | auto Func = []() { |
1160 | os_unfair_lock_s unfair_lock{}; |
1161 | os_unfair_lock_lock(&unfair_lock); |
1162 | }; |
1163 | ExpectRealtimeDeath(Func, "os_unfair_lock_lock" ); |
1164 | ExpectNonRealtimeSurvival(Func); |
1165 | } |
1166 | #endif // SANITIZER_APPLE |
1167 | |
1168 | #if SANITIZER_LINUX |
1169 | TEST(TestRtsanInterceptors, SpinLockLockDiesWhenRealtime) { |
1170 | pthread_spinlock_t spin_lock; |
1171 | pthread_spin_init(lock: &spin_lock, PTHREAD_PROCESS_SHARED); |
1172 | auto Func = [&]() { pthread_spin_lock(lock: &spin_lock); }; |
1173 | ExpectRealtimeDeath(Func, intercepted_method_name: "pthread_spin_lock" ); |
1174 | ExpectNonRealtimeSurvival(Func); |
1175 | } |
1176 | #endif |
1177 | |
1178 | TEST(TestRtsanInterceptors, PthreadCondSignalDiesWhenRealtime) { |
1179 | pthread_cond_t cond{}; |
1180 | ASSERT_EQ(0, pthread_cond_init(cond: &cond, cond_attr: nullptr)); |
1181 | |
1182 | auto Func = [&cond]() { pthread_cond_signal(cond: &cond); }; |
1183 | ExpectRealtimeDeath(Func, intercepted_method_name: "pthread_cond_signal" ); |
1184 | ExpectNonRealtimeSurvival(Func); |
1185 | |
1186 | pthread_cond_destroy(cond: &cond); |
1187 | } |
1188 | |
1189 | TEST(TestRtsanInterceptors, PthreadCondBroadcastDiesWhenRealtime) { |
1190 | pthread_cond_t cond{}; |
1191 | ASSERT_EQ(0, pthread_cond_init(cond: &cond, cond_attr: nullptr)); |
1192 | |
1193 | auto Func = [&cond]() { pthread_cond_broadcast(cond: &cond); }; |
1194 | ExpectRealtimeDeath(Func, intercepted_method_name: "pthread_cond_broadcast" ); |
1195 | ExpectNonRealtimeSurvival(Func); |
1196 | |
1197 | pthread_cond_destroy(cond: &cond); |
1198 | } |
1199 | |
1200 | TEST(TestRtsanInterceptors, PthreadCondWaitDiesWhenRealtime) { |
1201 | pthread_cond_t cond; |
1202 | pthread_mutex_t mutex; |
1203 | ASSERT_EQ(0, pthread_cond_init(cond: &cond, cond_attr: nullptr)); |
1204 | ASSERT_EQ(0, pthread_mutex_init(mutex: &mutex, mutexattr: nullptr)); |
1205 | |
1206 | auto Func = [&]() { pthread_cond_wait(cond: &cond, mutex: &mutex); }; |
1207 | ExpectRealtimeDeath(Func, intercepted_method_name: "pthread_cond_wait" ); |
1208 | // It's very difficult to test the success case here without doing some |
1209 | // sleeping, which is at the mercy of the scheduler. What's really important |
1210 | // here is the interception - so we're only testing that for now. |
1211 | |
1212 | pthread_cond_destroy(cond: &cond); |
1213 | pthread_mutex_destroy(mutex: &mutex); |
1214 | } |
1215 | |
1216 | class PthreadRwlockTest : public ::testing::Test { |
1217 | protected: |
1218 | void SetUp() override { |
1219 | pthread_rwlock_init(rwlock: &rw_lock, attr: nullptr); |
1220 | is_locked = false; |
1221 | } |
1222 | |
1223 | void TearDown() override { |
1224 | if (is_locked) |
1225 | Unlock(); |
1226 | |
1227 | pthread_rwlock_destroy(rwlock: &rw_lock); |
1228 | } |
1229 | |
1230 | void RdLock() { |
1231 | ASSERT_TRUE(!is_locked); |
1232 | pthread_rwlock_rdlock(rwlock: &rw_lock); |
1233 | is_locked = true; |
1234 | } |
1235 | |
1236 | void WrLock() { |
1237 | ASSERT_TRUE(!is_locked); |
1238 | pthread_rwlock_wrlock(rwlock: &rw_lock); |
1239 | is_locked = true; |
1240 | } |
1241 | |
1242 | void Unlock() { |
1243 | ASSERT_TRUE(is_locked); |
1244 | pthread_rwlock_unlock(rwlock: &rw_lock); |
1245 | is_locked = false; |
1246 | } |
1247 | |
1248 | private: |
1249 | pthread_rwlock_t rw_lock; |
1250 | bool is_locked; |
1251 | }; |
1252 | |
1253 | TEST_F(PthreadRwlockTest, PthreadRwlockRdlockDiesWhenRealtime) { |
1254 | auto Func = [this]() { RdLock(); }; |
1255 | ExpectRealtimeDeath(Func, intercepted_method_name: "pthread_rwlock_rdlock" ); |
1256 | } |
1257 | |
1258 | TEST_F(PthreadRwlockTest, PthreadRwlockRdlockSurvivesWhenNonRealtime) { |
1259 | auto Func = [this]() { RdLock(); }; |
1260 | ExpectNonRealtimeSurvival(Func); |
1261 | } |
1262 | |
1263 | TEST_F(PthreadRwlockTest, PthreadRwlockUnlockDiesWhenRealtime) { |
1264 | RdLock(); |
1265 | |
1266 | auto Func = [this]() { Unlock(); }; |
1267 | ExpectRealtimeDeath(Func, intercepted_method_name: "pthread_rwlock_unlock" ); |
1268 | } |
1269 | |
1270 | TEST_F(PthreadRwlockTest, PthreadRwlockUnlockSurvivesWhenNonRealtime) { |
1271 | RdLock(); |
1272 | |
1273 | auto Func = [this]() { Unlock(); }; |
1274 | ExpectNonRealtimeSurvival(Func); |
1275 | } |
1276 | |
1277 | TEST_F(PthreadRwlockTest, PthreadRwlockWrlockDiesWhenRealtime) { |
1278 | auto Func = [this]() { WrLock(); }; |
1279 | |
1280 | ExpectRealtimeDeath(Func, intercepted_method_name: "pthread_rwlock_wrlock" ); |
1281 | } |
1282 | |
1283 | TEST_F(PthreadRwlockTest, PthreadRwlockWrlockSurvivesWhenNonRealtime) { |
1284 | auto Func = [this]() { WrLock(); }; |
1285 | |
1286 | ExpectNonRealtimeSurvival(Func); |
1287 | } |
1288 | |
1289 | /* |
1290 | Sockets |
1291 | */ |
1292 | TEST(TestRtsanInterceptors, GetAddrInfoDiesWhenRealtime) { |
1293 | auto Func = []() { |
1294 | addrinfo *info{}; |
1295 | getaddrinfo(name: "localhost" , service: "http" , req: nullptr, pai: &info); |
1296 | }; |
1297 | ExpectRealtimeDeath(Func, intercepted_method_name: "getaddrinfo" ); |
1298 | ExpectNonRealtimeSurvival(Func); |
1299 | } |
1300 | |
1301 | TEST(TestRtsanInterceptors, GetNameInfoDiesWhenRealtime) { |
1302 | auto Func = []() { |
1303 | char host[NI_MAXHOST]; |
1304 | char serv[NI_MAXSERV]; |
1305 | getnameinfo(sa: nullptr, salen: 0, host: host, NI_MAXHOST, serv: serv, NI_MAXSERV, flags: 0); |
1306 | }; |
1307 | ExpectRealtimeDeath(Func, intercepted_method_name: "getnameinfo" ); |
1308 | ExpectNonRealtimeSurvival(Func); |
1309 | } |
1310 | |
1311 | TEST(TestRtsanInterceptors, BindingASocketDiesWhenRealtime) { |
1312 | auto Func = []() { EXPECT_NE(bind(fd: kNotASocketFd, addr: nullptr, len: 0), 0); }; |
1313 | ExpectRealtimeDeath(Func, intercepted_method_name: "bind" ); |
1314 | ExpectNonRealtimeSurvival(Func); |
1315 | } |
1316 | |
1317 | TEST(TestRtsanInterceptors, ListeningOnASocketDiesWhenRealtime) { |
1318 | auto Func = []() { EXPECT_NE(listen(fd: kNotASocketFd, n: 0), 0); }; |
1319 | ExpectRealtimeDeath(Func, intercepted_method_name: "listen" ); |
1320 | ExpectNonRealtimeSurvival(Func); |
1321 | } |
1322 | |
1323 | TEST(TestRtsanInterceptors, AcceptingASocketDiesWhenRealtime) { |
1324 | auto Func = []() { EXPECT_LT(accept(fd: kNotASocketFd, addr: nullptr, addr_len: nullptr), 0); }; |
1325 | ExpectRealtimeDeath(Func, intercepted_method_name: "accept" ); |
1326 | ExpectNonRealtimeSurvival(Func); |
1327 | } |
1328 | |
1329 | #if SANITIZER_INTERCEPT_ACCEPT4 |
1330 | TEST(TestRtsanInterceptors, Accepting4ASocketDiesWhenRealtime) { |
1331 | auto Func = []() { |
1332 | EXPECT_LT(accept4(fd: kNotASocketFd, addr: nullptr, addr_len: nullptr, flags: 0), 0); |
1333 | }; |
1334 | ExpectRealtimeDeath(Func, intercepted_method_name: "accept4" ); |
1335 | ExpectNonRealtimeSurvival(Func); |
1336 | } |
1337 | #endif |
1338 | |
1339 | TEST(TestRtsanInterceptors, ConnectingASocketDiesWhenRealtime) { |
1340 | auto Func = []() { EXPECT_NE(connect(fd: kNotASocketFd, addr: nullptr, len: 0), 0); }; |
1341 | ExpectRealtimeDeath(Func, intercepted_method_name: "connect" ); |
1342 | ExpectNonRealtimeSurvival(Func); |
1343 | } |
1344 | |
1345 | TEST(TestRtsanInterceptors, OpeningASocketDiesWhenRealtime) { |
1346 | auto Func = []() { socket(PF_INET, SOCK_STREAM, protocol: 0); }; |
1347 | ExpectRealtimeDeath(Func, intercepted_method_name: "socket" ); |
1348 | ExpectNonRealtimeSurvival(Func); |
1349 | } |
1350 | |
1351 | TEST(TestRtsanInterceptors, SendToASocketDiesWhenRealtime) { |
1352 | auto Func = []() { send(fd: 0, buf: nullptr, n: 0, flags: 0); }; |
1353 | ExpectRealtimeDeath(Func, intercepted_method_name: "send" ); |
1354 | ExpectNonRealtimeSurvival(Func); |
1355 | } |
1356 | |
1357 | TEST(TestRtsanInterceptors, SendmsgToASocketDiesWhenRealtime) { |
1358 | msghdr msg{}; |
1359 | auto Func = [&]() { sendmsg(fd: 0, message: &msg, flags: 0); }; |
1360 | ExpectRealtimeDeath(Func, intercepted_method_name: "sendmsg" ); |
1361 | ExpectNonRealtimeSurvival(Func); |
1362 | } |
1363 | |
1364 | #if SANITIZER_INTERCEPT_SENDMMSG |
1365 | TEST(TestRtsanInterceptors, SendmmsgOnASocketDiesWhenRealtime) { |
1366 | mmsghdr msg{}; |
1367 | auto Func = [&]() { sendmmsg(fd: 0, vmessages: &msg, vlen: 0, flags: 0); }; |
1368 | ExpectRealtimeDeath(Func, intercepted_method_name: "sendmmsg" ); |
1369 | ExpectNonRealtimeSurvival(Func); |
1370 | } |
1371 | #endif |
1372 | |
1373 | TEST(TestRtsanInterceptors, SendtoToASocketDiesWhenRealtime) { |
1374 | sockaddr addr{}; |
1375 | socklen_t len{}; |
1376 | auto Func = [&]() { sendto(fd: 0, buf: nullptr, n: 0, flags: 0, addr: &addr, addr_len: len); }; |
1377 | ExpectRealtimeDeath(Func, intercepted_method_name: "sendto" ); |
1378 | ExpectNonRealtimeSurvival(Func); |
1379 | } |
1380 | |
1381 | TEST(TestRtsanInterceptors, RecvFromASocketDiesWhenRealtime) { |
1382 | auto Func = []() { recv(fd: 0, buf: nullptr, n: 0, flags: 0); }; |
1383 | ExpectRealtimeDeath(Func, intercepted_method_name: "recv" ); |
1384 | ExpectNonRealtimeSurvival(Func); |
1385 | } |
1386 | |
1387 | TEST(TestRtsanInterceptors, RecvfromOnASocketDiesWhenRealtime) { |
1388 | sockaddr addr{}; |
1389 | socklen_t len{}; |
1390 | auto Func = [&]() { recvfrom(fd: 0, buf: nullptr, n: 0, flags: 0, addr: &addr, addr_len: &len); }; |
1391 | ExpectRealtimeDeath(Func, intercepted_method_name: "recvfrom" ); |
1392 | ExpectNonRealtimeSurvival(Func); |
1393 | } |
1394 | |
1395 | TEST(TestRtsanInterceptors, RecvmsgOnASocketDiesWhenRealtime) { |
1396 | msghdr msg{}; |
1397 | auto Func = [&]() { recvmsg(fd: 0, message: &msg, flags: 0); }; |
1398 | ExpectRealtimeDeath(Func, intercepted_method_name: "recvmsg" ); |
1399 | ExpectNonRealtimeSurvival(Func); |
1400 | } |
1401 | |
1402 | #if SANITIZER_INTERCEPT_RECVMMSG |
1403 | TEST(TestRtsanInterceptors, RecvmmsgOnASocketDiesWhenRealtime) { |
1404 | mmsghdr msg{}; |
1405 | auto Func = [&]() { recvmmsg(fd: 0, vmessages: &msg, vlen: 0, flags: 0, tmo: nullptr); }; |
1406 | ExpectRealtimeDeath(Func, intercepted_method_name: "recvmmsg" ); |
1407 | ExpectNonRealtimeSurvival(Func); |
1408 | } |
1409 | #endif |
1410 | |
1411 | TEST(TestRtsanInterceptors, ShutdownOnASocketDiesWhenRealtime) { |
1412 | auto Func = [&]() { shutdown(fd: 0, how: 0); }; |
1413 | ExpectRealtimeDeath(Func, intercepted_method_name: "shutdown" ); |
1414 | ExpectNonRealtimeSurvival(Func); |
1415 | } |
1416 | |
1417 | #if SANITIZER_INTERCEPT_GETSOCKNAME |
1418 | TEST(TestRtsanInterceptors, GetsocknameOnASocketDiesWhenRealtime) { |
1419 | sockaddr addr{}; |
1420 | socklen_t len{}; |
1421 | auto Func = [&]() { getsockname(fd: 0, addr: &addr, len: &len); }; |
1422 | ExpectRealtimeDeath(Func, intercepted_method_name: "getsockname" ); |
1423 | ExpectNonRealtimeSurvival(Func); |
1424 | } |
1425 | #endif |
1426 | |
1427 | #if SANITIZER_INTERCEPT_GETPEERNAME |
1428 | TEST(TestRtsanInterceptors, GetpeernameOnASocketDiesWhenRealtime) { |
1429 | sockaddr addr{}; |
1430 | socklen_t len{}; |
1431 | auto Func = [&]() { getpeername(fd: 0, addr: &addr, len: &len); }; |
1432 | ExpectRealtimeDeath(Func, intercepted_method_name: "getpeername" ); |
1433 | ExpectNonRealtimeSurvival(Func); |
1434 | } |
1435 | #endif |
1436 | |
1437 | #if SANITIZER_INTERCEPT_GETSOCKOPT |
1438 | TEST(TestRtsanInterceptors, GetsockoptOnASocketDiesWhenRealtime) { |
1439 | int val = 0; |
1440 | socklen_t len = static_cast<socklen_t>(sizeof(val)); |
1441 | auto Func = [&val, &len]() { |
1442 | getsockopt(fd: 0, SOL_SOCKET, SO_REUSEADDR, optval: &val, optlen: &len); |
1443 | }; |
1444 | ExpectRealtimeDeath(Func, intercepted_method_name: "getsockopt" ); |
1445 | ExpectNonRealtimeSurvival(Func); |
1446 | } |
1447 | |
1448 | TEST(TestRtsanInterceptors, SetsockoptOnASocketDiesWhenRealtime) { |
1449 | int val = 0; |
1450 | socklen_t len = static_cast<socklen_t>(sizeof(val)); |
1451 | auto Func = [&val, &len]() { |
1452 | setsockopt(fd: 0, SOL_SOCKET, SO_REUSEADDR, optval: &val, optlen: len); |
1453 | }; |
1454 | ExpectRealtimeDeath(Func, intercepted_method_name: "setsockopt" ); |
1455 | ExpectNonRealtimeSurvival(Func); |
1456 | } |
1457 | #endif |
1458 | |
1459 | TEST(TestRtsanInterceptors, SocketpairDiesWhenRealtime) { |
1460 | int pair[2]{}; |
1461 | auto Func = [&pair]() { socketpair(domain: 0, type: 0, protocol: 0, fds: pair); }; |
1462 | ExpectRealtimeDeath(Func, intercepted_method_name: "socketpair" ); |
1463 | ExpectNonRealtimeSurvival(Func); |
1464 | } |
1465 | |
1466 | /* |
1467 | I/O Multiplexing |
1468 | */ |
1469 | |
1470 | TEST(TestRtsanInterceptors, PollDiesWhenRealtime) { |
1471 | struct pollfd fds[1]; |
1472 | fds[0].fd = 0; |
1473 | fds[0].events = POLLIN; |
1474 | |
1475 | auto Func = [&fds]() { poll(fds: fds, nfds: 1, timeout: 0); }; |
1476 | |
1477 | ExpectRealtimeDeath(Func, intercepted_method_name: "poll" ); |
1478 | ExpectNonRealtimeSurvival(Func); |
1479 | } |
1480 | |
1481 | #if !SANITIZER_APPLE |
1482 | // FIXME: This should work on Darwin as well |
1483 | // see the comment near the interceptor |
1484 | TEST(TestRtsanInterceptors, SelectDiesWhenRealtime) { |
1485 | fd_set readfds; |
1486 | FD_ZERO(&readfds); |
1487 | FD_SET(0, &readfds); |
1488 | struct timeval timeout = {.tv_sec: 0, .tv_usec: 0}; |
1489 | |
1490 | auto Func = [&readfds, &timeout]() { |
1491 | select(nfds: 1, readfds: &readfds, writefds: nullptr, exceptfds: nullptr, timeout: &timeout); |
1492 | }; |
1493 | ExpectRealtimeDeath(Func, intercepted_method_name: "select" ); |
1494 | ExpectNonRealtimeSurvival(Func); |
1495 | } |
1496 | #endif |
1497 | |
1498 | TEST(TestRtsanInterceptors, PSelectDiesWhenRealtime) { |
1499 | fd_set readfds; |
1500 | FD_ZERO(&readfds); |
1501 | FD_SET(0, &readfds); |
1502 | struct timespec timeout = {.tv_sec: 0, .tv_nsec: 0}; |
1503 | |
1504 | auto Func = [&]() { |
1505 | pselect(nfds: 1, readfds: &readfds, writefds: nullptr, exceptfds: nullptr, timeout: &timeout, sigmask: nullptr); |
1506 | }; |
1507 | ExpectRealtimeDeath(Func, intercepted_method_name: "pselect" ); |
1508 | ExpectNonRealtimeSurvival(Func); |
1509 | } |
1510 | |
1511 | #if SANITIZER_INTERCEPT_EPOLL |
1512 | TEST(TestRtsanInterceptors, EpollCreateDiesWhenRealtime) { |
1513 | auto Func = []() { epoll_create(size: 1); }; |
1514 | ExpectRealtimeDeath(Func, intercepted_method_name: "epoll_create" ); |
1515 | ExpectNonRealtimeSurvival(Func); |
1516 | } |
1517 | |
1518 | TEST(TestRtsanInterceptors, EpollCreate1DiesWhenRealtime) { |
1519 | auto Func = []() { epoll_create1(EPOLL_CLOEXEC); }; |
1520 | ExpectRealtimeDeath(Func, intercepted_method_name: "epoll_create1" ); |
1521 | ExpectNonRealtimeSurvival(Func); |
1522 | } |
1523 | |
1524 | class EpollTest : public ::testing::Test { |
1525 | protected: |
1526 | void SetUp() override { |
1527 | epfd = epoll_create1(EPOLL_CLOEXEC); |
1528 | ASSERT_GE(epfd, 0); |
1529 | } |
1530 | |
1531 | void TearDown() override { |
1532 | if (epfd >= 0) |
1533 | close(epfd); |
1534 | } |
1535 | |
1536 | int GetEpollFd() { return epfd; } |
1537 | |
1538 | private: |
1539 | int epfd = -1; |
1540 | }; |
1541 | |
1542 | TEST_F(EpollTest, EpollCtlDiesWhenRealtime) { |
1543 | auto Func = [this]() { |
1544 | struct epoll_event event = {.events = EPOLLIN, .data = {.fd = 0}}; |
1545 | epoll_ctl(GetEpollFd(), EPOLL_CTL_ADD, 0, &event); |
1546 | }; |
1547 | ExpectRealtimeDeath(Func, intercepted_method_name: "epoll_ctl" ); |
1548 | ExpectNonRealtimeSurvival(Func); |
1549 | } |
1550 | |
1551 | TEST_F(EpollTest, EpollWaitDiesWhenRealtime) { |
1552 | auto Func = [this]() { |
1553 | struct epoll_event events[1]; |
1554 | epoll_wait(GetEpollFd(), events, 1, 0); |
1555 | }; |
1556 | |
1557 | ExpectRealtimeDeath(Func, intercepted_method_name: "epoll_wait" ); |
1558 | ExpectNonRealtimeSurvival(Func); |
1559 | } |
1560 | |
1561 | TEST_F(EpollTest, EpollPWaitDiesWhenRealtime) { |
1562 | auto Func = [this]() { |
1563 | struct epoll_event events[1]; |
1564 | epoll_pwait(GetEpollFd(), events, 1, 0, nullptr); |
1565 | }; |
1566 | |
1567 | ExpectRealtimeDeath(Func, intercepted_method_name: "epoll_pwait" ); |
1568 | ExpectNonRealtimeSurvival(Func); |
1569 | } |
1570 | #endif // SANITIZER_INTERCEPT_EPOLL |
1571 | |
1572 | #if SANITIZER_INTERCEPT_PPOLL |
1573 | TEST(TestRtsanInterceptors, PpollDiesWhenRealtime) { |
1574 | struct pollfd fds[1]; |
1575 | fds[0].fd = 0; |
1576 | fds[0].events = POLLIN; |
1577 | |
1578 | timespec ts = {.tv_sec: 0, .tv_nsec: 0}; |
1579 | |
1580 | auto Func = [&fds, &ts]() { ppoll(fds: fds, nfds: 1, timeout: &ts, ss: nullptr); }; |
1581 | |
1582 | ExpectRealtimeDeath(Func, intercepted_method_name: "ppoll" ); |
1583 | ExpectNonRealtimeSurvival(Func); |
1584 | } |
1585 | #endif |
1586 | |
1587 | #if SANITIZER_INTERCEPT_KQUEUE |
1588 | TEST(TestRtsanInterceptors, KqueueDiesWhenRealtime) { |
1589 | auto Func = []() { kqueue(); }; |
1590 | ExpectRealtimeDeath(Func, "kqueue" ); |
1591 | ExpectNonRealtimeSurvival(Func); |
1592 | } |
1593 | |
1594 | class KqueueTest : public ::testing::Test { |
1595 | protected: |
1596 | void SetUp() override { |
1597 | kq = kqueue(); |
1598 | ASSERT_GE(kq, 0); |
1599 | } |
1600 | |
1601 | void TearDown() override { |
1602 | if (kq >= 0) |
1603 | close(kq); |
1604 | } |
1605 | |
1606 | int GetKqueueFd() { return kq; } |
1607 | |
1608 | private: |
1609 | int kq = -1; |
1610 | }; |
1611 | |
1612 | TEST_F(KqueueTest, KeventDiesWhenRealtime) { |
1613 | struct kevent event; |
1614 | EV_SET(&event, 0, EVFILT_READ, EV_ADD, 0, 0, nullptr); |
1615 | struct timespec timeout = {0, 0}; |
1616 | |
1617 | auto Func = [this, event, timeout]() { |
1618 | kevent(GetKqueueFd(), &event, 1, nullptr, 0, &timeout); |
1619 | }; |
1620 | |
1621 | ExpectRealtimeDeath(Func, "kevent" ); |
1622 | ExpectNonRealtimeSurvival(Func); |
1623 | } |
1624 | |
1625 | TEST_F(KqueueTest, Kevent64DiesWhenRealtime) { |
1626 | struct kevent64_s event; |
1627 | EV_SET64(&event, 0, EVFILT_READ, EV_ADD, 0, 0, 0, 0, 0); |
1628 | struct timespec timeout = {0, 0}; |
1629 | |
1630 | auto Func = [this, event, timeout]() { |
1631 | kevent64(GetKqueueFd(), &event, 1, nullptr, 0, 0, &timeout); |
1632 | }; |
1633 | |
1634 | ExpectRealtimeDeath(Func, "kevent64" ); |
1635 | ExpectNonRealtimeSurvival(Func); |
1636 | } |
1637 | #endif // SANITIZER_INTERCEPT_KQUEUE |
1638 | |
1639 | #if SANITIZER_LINUX |
1640 | TEST(TestRtsanInterceptors, InotifyInitDiesWhenRealtime) { |
1641 | auto Func = []() { inotify_init(); }; |
1642 | ExpectRealtimeDeath(Func, intercepted_method_name: "inotify_init" ); |
1643 | ExpectNonRealtimeSurvival(Func); |
1644 | } |
1645 | |
1646 | TEST(TestRtsanInterceptors, InotifyInit1DiesWhenRealtime) { |
1647 | auto Func = []() { inotify_init1(flags: 0); }; |
1648 | ExpectRealtimeDeath(Func, intercepted_method_name: "inotify_init1" ); |
1649 | ExpectNonRealtimeSurvival(Func); |
1650 | } |
1651 | |
1652 | TEST(TestRtsanInterceptors, InotifyAddWatchDiesWhenRealtime) { |
1653 | int fd = inotify_init(); |
1654 | EXPECT_THAT(fd, Ne(-1)); |
1655 | auto Func = [fd]() { |
1656 | inotify_add_watch(fd: fd, name: "/tmp/rtsan_inotify" , IN_CREATE); |
1657 | }; |
1658 | ExpectRealtimeDeath(Func, intercepted_method_name: "inotify_add_watch" ); |
1659 | ExpectNonRealtimeSurvival(Func); |
1660 | } |
1661 | |
1662 | TEST(TestRtsanInterceptors, InotifyRmWatchDiesWhenRealtime) { |
1663 | int fd = inotify_init(); |
1664 | EXPECT_THAT(fd, Ne(-1)); |
1665 | auto Func = [fd]() { inotify_rm_watch(fd: fd, wd: -1); }; |
1666 | ExpectRealtimeDeath(Func, intercepted_method_name: "inotify_rm_watch" ); |
1667 | ExpectNonRealtimeSurvival(Func); |
1668 | } |
1669 | |
1670 | TEST(TestRtsanInterceptors, TimerfdCreateDiesWhenRealtime) { |
1671 | auto Func = []() { timerfd_create(CLOCK_MONOTONIC, flags: 0); }; |
1672 | ExpectRealtimeDeath(Func, intercepted_method_name: "timerfd_create" ); |
1673 | ExpectNonRealtimeSurvival(Func); |
1674 | } |
1675 | |
1676 | TEST(TestRtsanInterceptors, TimerfdSettimeDiesWhenRealtime) { |
1677 | int fd = timerfd_create(CLOCK_MONOTONIC, flags: 0); |
1678 | EXPECT_THAT(fd, Ne(-1)); |
1679 | auto ts = itimerspec{.it_interval: {.tv_sec: 0, .tv_nsec: 0}, .it_value: {.tv_sec: 0, .tv_nsec: 0}}; |
1680 | auto Func = [fd, ts]() { timerfd_settime(ufd: fd, flags: 0, utmr: &ts, NULL); }; |
1681 | ExpectRealtimeDeath(Func, intercepted_method_name: "timerfd_settime" ); |
1682 | ExpectNonRealtimeSurvival(Func); |
1683 | } |
1684 | |
1685 | TEST(TestRtsanInterceptors, TimerfdGettimeDiesWhenRealtime) { |
1686 | int fd = timerfd_create(CLOCK_MONOTONIC, flags: 0); |
1687 | EXPECT_THAT(fd, Ne(-1)); |
1688 | itimerspec ts{}; |
1689 | auto Func = [fd, &ts]() { timerfd_gettime(ufd: fd, otmr: &ts); }; |
1690 | ExpectRealtimeDeath(Func, intercepted_method_name: "timerfd_gettime" ); |
1691 | ExpectNonRealtimeSurvival(Func); |
1692 | } |
1693 | |
1694 | TEST(TestRtsanInterceptors, EventfdDiesWhenRealtime) { |
1695 | auto Func = []() { eventfd(EFD_CLOEXEC, flags: 0); }; |
1696 | ExpectRealtimeDeath(Func, intercepted_method_name: "eventfd" ); |
1697 | ExpectNonRealtimeSurvival(Func); |
1698 | } |
1699 | #endif |
1700 | |
1701 | TEST(TestRtsanInterceptors, MkfifoDiesWhenRealtime) { |
1702 | auto Func = []() { mkfifo(path: "/tmp/rtsan_test_fifo" , mode: 0); }; |
1703 | ExpectRealtimeDeath(Func, intercepted_method_name: "mkfifo" ); |
1704 | ExpectNonRealtimeSurvival(Func); |
1705 | } |
1706 | |
1707 | TEST(TestRtsanInterceptors, PipeDiesWhenRealtime) { |
1708 | int fds[2]; |
1709 | auto Func = [&fds]() { pipe(fds); }; |
1710 | ExpectRealtimeDeath(Func, intercepted_method_name: "pipe" ); |
1711 | ExpectNonRealtimeSurvival(Func); |
1712 | } |
1713 | |
1714 | #if !SANITIZER_APPLE |
1715 | TEST(TestRtsanInterceptors, Pipe2DiesWhenRealtime) { |
1716 | int fds[2]; |
1717 | auto Func = [&fds]() { pipe2(fds, O_CLOEXEC); }; |
1718 | ExpectRealtimeDeath(Func, intercepted_method_name: "pipe2" ); |
1719 | ExpectNonRealtimeSurvival(Func); |
1720 | } |
1721 | #endif |
1722 | |
1723 | #pragma clang diagnostic push |
1724 | #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
1725 | TEST(TestRtsanInterceptors, SyscallDiesWhenRealtime) { |
1726 | auto Func = []() { syscall(SYS_getpid); }; |
1727 | ExpectRealtimeDeath(Func, intercepted_method_name: "syscall" ); |
1728 | ExpectNonRealtimeSurvival(Func); |
1729 | } |
1730 | |
1731 | TEST(TestRtsanInterceptors, GetPidReturnsSame) { |
1732 | int pid = syscall(SYS_getpid); |
1733 | EXPECT_THAT(pid, Ne(-1)); |
1734 | |
1735 | EXPECT_THAT(getpid(), Eq(pid)); |
1736 | } |
1737 | #pragma clang diagnostic pop |
1738 | |
1739 | #endif // SANITIZER_POSIX |
1740 | |