xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/rtsan/tests/rtsan_test_interceptors.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 "gtest/gtest.h"
12 
13 #include <sanitizer_common/sanitizer_platform.h>
14 #include <sanitizer_common/sanitizer_platform_interceptors.h>
15 
16 #include "rtsan_test_utilities.h"
17 
18 #if SANITIZER_APPLE
19 #include <libkern/OSAtomic.h>
20 #include <os/lock.h>
21 #endif
22 
23 #if SANITIZER_INTERCEPT_MEMALIGN || SANITIZER_INTERCEPT_PVALLOC
24 #include <malloc.h>
25 #endif
26 
27 #include <atomic>
28 #include <chrono>
29 #include <string>
30 #include <thread>
31 
32 #include <fcntl.h>
33 #include <pthread.h>
34 #include <stdio.h>
35 #include <sys/socket.h>
36 
37 using namespace testing;
38 using namespace rtsan_testing;
39 using namespace std::chrono_literals;
40 
41 void *FakeThreadEntryPoint(void *) { return nullptr; }
42 
43 class RtsanFileTest : public ::testing::Test {
44 protected:
45   void SetUp() override {
46     const ::testing::TestInfo *const test_info =
47         ::testing::UnitTest::GetInstance()->current_test_info();
48     file_path_ = std::string("/tmp/rtsan_temporary_test_file_") +
49                  test_info->name() + ".txt";
50     RemoveTemporaryFile();
51   }
52 
53   // Gets a file path with the test's name in it
54   // This file will be removed if it exists at the end of the test
55   const char *GetTemporaryFilePath() const { return file_path_.c_str(); }
56 
57   void TearDown() override { RemoveTemporaryFile(); }
58 
59 private:
60   void RemoveTemporaryFile() const { std::remove(GetTemporaryFilePath()); }
61   std::string file_path_;
62 };
63 
64 /*
65     Allocation and deallocation
66 */
67 
68 TEST(TestRtsanInterceptors, MallocDiesWhenRealtime) {
69   auto Func = []() { EXPECT_NE(nullptr, malloc(1)); };
70   ExpectRealtimeDeath(Func, "malloc");
71   ExpectNonRealtimeSurvival(Func);
72 }
73 
74 TEST(TestRtsanInterceptors, ReallocDiesWhenRealtime) {
75   void *ptr_1 = malloc(1);
76   auto Func = [ptr_1]() { EXPECT_NE(nullptr, realloc(ptr_1, 8)); };
77   ExpectRealtimeDeath(Func, "realloc");
78   ExpectNonRealtimeSurvival(Func);
79 }
80 
81 #if SANITIZER_APPLE
82 TEST(TestRtsanInterceptors, ReallocfDiesWhenRealtime) {
83   void *ptr_1 = malloc(1);
84   auto Func = [ptr_1]() { EXPECT_NE(nullptr, reallocf(ptr_1, 8)); };
85   ExpectRealtimeDeath(Func, "reallocf");
86   ExpectNonRealtimeSurvival(Func);
87 }
88 #endif
89 
90 TEST(TestRtsanInterceptors, VallocDiesWhenRealtime) {
91   auto Func = []() { EXPECT_NE(nullptr, valloc(4)); };
92   ExpectRealtimeDeath(Func, "valloc");
93   ExpectNonRealtimeSurvival(Func);
94 }
95 
96 #if SANITIZER_INTERCEPT_ALIGNED_ALLOC
97 TEST(TestRtsanInterceptors, AlignedAllocDiesWhenRealtime) {
98   auto Func = []() { EXPECT_NE(nullptr, aligned_alloc(16, 32)); };
99   ExpectRealtimeDeath(Func, "aligned_alloc");
100   ExpectNonRealtimeSurvival(Func);
101 }
102 #endif
103 
104 // free_sized and free_aligned_sized (both C23) are not yet supported
105 TEST(TestRtsanInterceptors, FreeDiesWhenRealtime) {
106   void *ptr_1 = malloc(1);
107   void *ptr_2 = malloc(1);
108   ExpectRealtimeDeath([ptr_1]() { free(ptr_1); }, "free");
109   ExpectNonRealtimeSurvival([ptr_2]() { free(ptr_2); });
110 
111   // Prevent malloc/free pair being optimised out
112   ASSERT_NE(nullptr, ptr_1);
113   ASSERT_NE(nullptr, ptr_2);
114 }
115 
116 TEST(TestRtsanInterceptors, FreeSurvivesWhenRealtimeIfArgumentIsNull) {
117   RealtimeInvoke([]() { free(NULL); });
118   ExpectNonRealtimeSurvival([]() { free(NULL); });
119 }
120 
121 TEST(TestRtsanInterceptors, PosixMemalignDiesWhenRealtime) {
122   auto Func = []() {
123     void *ptr;
124     posix_memalign(&ptr, 4, 4);
125   };
126   ExpectRealtimeDeath(Func, "posix_memalign");
127   ExpectNonRealtimeSurvival(Func);
128 }
129 
130 #if SANITIZER_INTERCEPT_MEMALIGN
131 TEST(TestRtsanInterceptors, MemalignDiesWhenRealtime) {
132   auto Func = []() { EXPECT_NE(memalign(2, 2048), nullptr); };
133   ExpectRealtimeDeath(Func, "memalign");
134   ExpectNonRealtimeSurvival(Func);
135 }
136 #endif
137 
138 #if SANITIZER_INTERCEPT_PVALLOC
139 TEST(TestRtsanInterceptors, PvallocDiesWhenRealtime) {
140   auto Func = []() { EXPECT_NE(pvalloc(2048), nullptr); };
141   ExpectRealtimeDeath(Func, "pvalloc");
142   ExpectNonRealtimeSurvival(Func);
143 }
144 #endif
145 
146 /*
147     Sleeping
148 */
149 
150 TEST(TestRtsanInterceptors, SleepDiesWhenRealtime) {
151   auto Func = []() { sleep(0u); };
152   ExpectRealtimeDeath(Func, "sleep");
153   ExpectNonRealtimeSurvival(Func);
154 }
155 
156 TEST(TestRtsanInterceptors, UsleepDiesWhenRealtime) {
157   auto Func = []() { usleep(1u); };
158   ExpectRealtimeDeath(Func, "usleep");
159   ExpectNonRealtimeSurvival(Func);
160 }
161 
162 TEST(TestRtsanInterceptors, NanosleepDiesWhenRealtime) {
163   auto Func = []() {
164     timespec T{};
165     nanosleep(&T, &T);
166   };
167   ExpectRealtimeDeath(Func, "nanosleep");
168   ExpectNonRealtimeSurvival(Func);
169 }
170 
171 /*
172     Filesystem
173 */
174 
175 TEST_F(RtsanFileTest, OpenDiesWhenRealtime) {
176   auto func = [this]() { open(GetTemporaryFilePath(), O_RDONLY); };
177   ExpectRealtimeDeath(func, "open");
178   ExpectNonRealtimeSurvival(func);
179 }
180 
181 TEST_F(RtsanFileTest, OpenatDiesWhenRealtime) {
182   auto func = [this]() { openat(0, GetTemporaryFilePath(), O_RDONLY); };
183   ExpectRealtimeDeath(func, "openat");
184   ExpectNonRealtimeSurvival(func);
185 }
186 
187 TEST_F(RtsanFileTest, OpenCreatesFileWithProperMode) {
188   const int mode = S_IRGRP | S_IROTH | S_IRUSR | S_IWUSR;
189 
190   const int fd = open(GetTemporaryFilePath(), O_CREAT | O_WRONLY, mode);
191   ASSERT_THAT(fd, Ne(-1));
192   close(fd);
193 
194   struct stat st;
195   ASSERT_THAT(stat(GetTemporaryFilePath(), &st), Eq(0));
196 
197   // Mask st_mode to get permission bits only
198   ASSERT_THAT(st.st_mode & 0777, Eq(mode));
199 }
200 
201 TEST_F(RtsanFileTest, CreatDiesWhenRealtime) {
202   auto func = [this]() { creat(GetTemporaryFilePath(), S_IWOTH | S_IROTH); };
203   ExpectRealtimeDeath(func, "creat");
204   ExpectNonRealtimeSurvival(func);
205 }
206 
207 TEST(TestRtsanInterceptors, FcntlDiesWhenRealtime) {
208   auto func = []() { fcntl(0, F_GETFL); };
209   ExpectRealtimeDeath(func, "fcntl");
210   ExpectNonRealtimeSurvival(func);
211 }
212 
213 TEST_F(RtsanFileTest, FcntlFlockDiesWhenRealtime) {
214   int fd = creat(GetTemporaryFilePath(), S_IRUSR | S_IWUSR);
215   ASSERT_THAT(fd, Ne(-1));
216 
217   auto func = [fd]() {
218     struct flock lock {};
219     lock.l_type = F_RDLCK;
220     lock.l_whence = SEEK_SET;
221     lock.l_start = 0;
222     lock.l_len = 0;
223     lock.l_pid = ::getpid();
224 
225     ASSERT_THAT(fcntl(fd, F_GETLK, &lock), Eq(0));
226     ASSERT_THAT(lock.l_type, F_UNLCK);
227   };
228   ExpectRealtimeDeath(func, "fcntl");
229   ExpectNonRealtimeSurvival(func);
230 
231   close(fd);
232 }
233 
234 TEST_F(RtsanFileTest, FcntlSetFdDiesWhenRealtime) {
235   int fd = creat(GetTemporaryFilePath(), S_IRUSR | S_IWUSR);
236   ASSERT_THAT(fd, Ne(-1));
237 
238   auto func = [fd]() {
239     int old_flags = fcntl(fd, F_GETFD);
240     ASSERT_THAT(fcntl(fd, F_SETFD, FD_CLOEXEC), Eq(0));
241 
242     int flags = fcntl(fd, F_GETFD);
243     ASSERT_THAT(flags, Ne(-1));
244     ASSERT_THAT(flags & FD_CLOEXEC, Eq(FD_CLOEXEC));
245 
246     ASSERT_THAT(fcntl(fd, F_SETFD, old_flags), Eq(0));
247     ASSERT_THAT(fcntl(fd, F_GETFD), Eq(old_flags));
248   };
249 
250   ExpectRealtimeDeath(func, "fcntl");
251   ExpectNonRealtimeSurvival(func);
252 
253   close(fd);
254 }
255 
256 TEST(TestRtsanInterceptors, CloseDiesWhenRealtime) {
257   auto func = []() { close(0); };
258   ExpectRealtimeDeath(func, "close");
259   ExpectNonRealtimeSurvival(func);
260 }
261 
262 TEST_F(RtsanFileTest, FopenDiesWhenRealtime) {
263   auto func = [this]() {
264     auto fd = fopen(GetTemporaryFilePath(), "w");
265     EXPECT_THAT(fd, Ne(nullptr));
266   };
267   ExpectRealtimeDeath(func, "fopen");
268   ExpectNonRealtimeSurvival(func);
269 }
270 
271 TEST_F(RtsanFileTest, FreadDiesWhenRealtime) {
272   auto fd = fopen(GetTemporaryFilePath(), "w");
273   auto func = [fd]() {
274     char c{};
275     fread(&c, 1, 1, fd);
276   };
277   ExpectRealtimeDeath(func, "fread");
278   ExpectNonRealtimeSurvival(func);
279   if (fd != nullptr)
280     fclose(fd);
281 }
282 
283 TEST_F(RtsanFileTest, FwriteDiesWhenRealtime) {
284   auto fd = fopen(GetTemporaryFilePath(), "w");
285   ASSERT_NE(nullptr, fd);
286   auto message = "Hello, world!";
287   auto func = [&]() { fwrite(&message, 1, 4, fd); };
288   ExpectRealtimeDeath(func, "fwrite");
289   ExpectNonRealtimeSurvival(func);
290 }
291 
292 TEST_F(RtsanFileTest, FcloseDiesWhenRealtime) {
293   auto fd = fopen(GetTemporaryFilePath(), "w");
294   EXPECT_THAT(fd, Ne(nullptr));
295   auto func = [fd]() { fclose(fd); };
296   ExpectRealtimeDeath(func, "fclose");
297   ExpectNonRealtimeSurvival(func);
298 }
299 
300 TEST(TestRtsanInterceptors, PutsDiesWhenRealtime) {
301   auto func = []() { puts("Hello, world!\n"); };
302   ExpectRealtimeDeath(func);
303   ExpectNonRealtimeSurvival(func);
304 }
305 
306 TEST_F(RtsanFileTest, FputsDiesWhenRealtime) {
307   auto fd = fopen(GetTemporaryFilePath(), "w");
308   ASSERT_THAT(fd, Ne(nullptr)) << errno;
309   auto func = [fd]() { fputs("Hello, world!\n", fd); };
310   ExpectRealtimeDeath(func);
311   ExpectNonRealtimeSurvival(func);
312   if (fd != nullptr)
313     fclose(fd);
314 }
315 
316 /*
317     Concurrency
318 */
319 
320 TEST(TestRtsanInterceptors, PthreadCreateDiesWhenRealtime) {
321   auto Func = []() {
322     pthread_t thread{};
323     const pthread_attr_t attr{};
324     struct thread_info *thread_info;
325     pthread_create(&thread, &attr, &FakeThreadEntryPoint, thread_info);
326   };
327   ExpectRealtimeDeath(Func, "pthread_create");
328   ExpectNonRealtimeSurvival(Func);
329 }
330 
331 TEST(TestRtsanInterceptors, PthreadMutexLockDiesWhenRealtime) {
332   auto Func = []() {
333     pthread_mutex_t mutex{};
334     pthread_mutex_lock(&mutex);
335   };
336 
337   ExpectRealtimeDeath(Func, "pthread_mutex_lock");
338   ExpectNonRealtimeSurvival(Func);
339 }
340 
341 TEST(TestRtsanInterceptors, PthreadMutexUnlockDiesWhenRealtime) {
342   auto Func = []() {
343     pthread_mutex_t mutex{};
344     pthread_mutex_unlock(&mutex);
345   };
346 
347   ExpectRealtimeDeath(Func, "pthread_mutex_unlock");
348   ExpectNonRealtimeSurvival(Func);
349 }
350 
351 TEST(TestRtsanInterceptors, PthreadMutexJoinDiesWhenRealtime) {
352   auto Func = []() {
353     pthread_t thread{};
354     pthread_join(thread, nullptr);
355   };
356 
357   ExpectRealtimeDeath(Func, "pthread_join");
358   ExpectNonRealtimeSurvival(Func);
359 }
360 
361 #if SANITIZER_APPLE
362 
363 #pragma clang diagnostic push
364 // OSSpinLockLock is deprecated, but still in use in libc++
365 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
366 TEST(TestRtsanInterceptors, OsSpinLockLockDiesWhenRealtime) {
367   auto Func = []() {
368     OSSpinLock spin_lock{};
369     OSSpinLockLock(&spin_lock);
370   };
371   ExpectRealtimeDeath(Func, "OSSpinLockLock");
372   ExpectNonRealtimeSurvival(Func);
373 }
374 #pragma clang diagnostic pop
375 
376 TEST(TestRtsanInterceptors, OsUnfairLockLockDiesWhenRealtime) {
377   auto Func = []() {
378     os_unfair_lock_s unfair_lock{};
379     os_unfair_lock_lock(&unfair_lock);
380   };
381   ExpectRealtimeDeath(Func, "os_unfair_lock_lock");
382   ExpectNonRealtimeSurvival(Func);
383 }
384 #endif
385 
386 #if SANITIZER_LINUX
387 TEST(TestRtsanInterceptors, SpinLockLockDiesWhenRealtime) {
388   pthread_spinlock_t spin_lock;
389   pthread_spin_init(&spin_lock, PTHREAD_PROCESS_SHARED);
390   auto Func = [&]() { pthread_spin_lock(&spin_lock); };
391   ExpectRealtimeDeath(Func, "pthread_spin_lock");
392   ExpectNonRealtimeSurvival(Func);
393 }
394 #endif
395 
396 TEST(TestRtsanInterceptors, PthreadCondSignalDiesWhenRealtime) {
397   pthread_cond_t cond{};
398   pthread_cond_init(&cond, NULL);
399 
400   auto Func = [&cond]() { pthread_cond_signal(&cond); };
401   ExpectRealtimeDeath(Func, "pthread_cond_signal");
402   ExpectNonRealtimeSurvival(Func);
403 
404   pthread_cond_destroy(&cond);
405 }
406 
407 TEST(TestRtsanInterceptors, PthreadCondBroadcastDiesWhenRealtime) {
408   pthread_cond_t cond{};
409   pthread_cond_init(&cond, NULL);
410 
411   auto Func = [&cond]() { pthread_cond_broadcast(&cond); };
412   ExpectRealtimeDeath(Func, "pthread_cond_broadcast");
413   ExpectNonRealtimeSurvival(Func);
414 
415   pthread_cond_destroy(&cond);
416 }
417 
418 TEST(TestRtsanInterceptors, PthreadCondWaitDiesWhenRealtime) {
419   pthread_cond_t cond;
420   pthread_mutex_t mutex;
421   ASSERT_EQ(0, pthread_cond_init(&cond, nullptr));
422   ASSERT_EQ(0, pthread_mutex_init(&mutex, nullptr));
423 
424   auto Func = [&]() { pthread_cond_wait(&cond, &mutex); };
425   ExpectRealtimeDeath(Func, "pthread_cond_wait");
426   // It's very difficult to test the success case here without doing some
427   // sleeping, which is at the mercy of the scheduler. What's really important
428   // here is the interception - so we're only testing that for now.
429 
430   pthread_cond_destroy(&cond);
431   pthread_mutex_destroy(&mutex);
432 }
433 
434 TEST(TestRtsanInterceptors, PthreadRwlockRdlockDiesWhenRealtime) {
435   auto Func = []() {
436     pthread_rwlock_t rw_lock;
437     pthread_rwlock_rdlock(&rw_lock);
438   };
439   ExpectRealtimeDeath(Func, "pthread_rwlock_rdlock");
440   ExpectNonRealtimeSurvival(Func);
441 }
442 
443 TEST(TestRtsanInterceptors, PthreadRwlockUnlockDiesWhenRealtime) {
444   auto Func = []() {
445     pthread_rwlock_t rw_lock;
446     pthread_rwlock_unlock(&rw_lock);
447   };
448   ExpectRealtimeDeath(Func, "pthread_rwlock_unlock");
449   ExpectNonRealtimeSurvival(Func);
450 }
451 
452 TEST(TestRtsanInterceptors, PthreadRwlockWrlockDiesWhenRealtime) {
453   auto Func = []() {
454     pthread_rwlock_t rw_lock;
455     pthread_rwlock_wrlock(&rw_lock);
456   };
457   ExpectRealtimeDeath(Func, "pthread_rwlock_wrlock");
458   ExpectNonRealtimeSurvival(Func);
459 }
460 
461 /*
462     Sockets
463 */
464 TEST(TestRtsanInterceptors, OpeningASocketDiesWhenRealtime) {
465   auto Func = []() { socket(PF_INET, SOCK_STREAM, 0); };
466   ExpectRealtimeDeath(Func, "socket");
467   ExpectNonRealtimeSurvival(Func);
468 }
469 
470 TEST(TestRtsanInterceptors, SendToASocketDiesWhenRealtime) {
471   auto Func = []() { send(0, nullptr, 0, 0); };
472   ExpectRealtimeDeath(Func, "send");
473   ExpectNonRealtimeSurvival(Func);
474 }
475 
476 TEST(TestRtsanInterceptors, SendmsgToASocketDiesWhenRealtime) {
477   msghdr msg{};
478   auto Func = [&]() { sendmsg(0, &msg, 0); };
479   ExpectRealtimeDeath(Func, "sendmsg");
480   ExpectNonRealtimeSurvival(Func);
481 }
482 
483 TEST(TestRtsanInterceptors, SendtoToASocketDiesWhenRealtime) {
484   sockaddr addr{};
485   socklen_t len{};
486   auto Func = [&]() { sendto(0, nullptr, 0, 0, &addr, len); };
487   ExpectRealtimeDeath(Func, "sendto");
488   ExpectNonRealtimeSurvival(Func);
489 }
490 
491 TEST(TestRtsanInterceptors, RecvFromASocketDiesWhenRealtime) {
492   auto Func = []() { recv(0, nullptr, 0, 0); };
493   ExpectRealtimeDeath(Func, "recv");
494   ExpectNonRealtimeSurvival(Func);
495 }
496 
497 TEST(TestRtsanInterceptors, RecvfromOnASocketDiesWhenRealtime) {
498   sockaddr addr{};
499   socklen_t len{};
500   auto Func = [&]() { recvfrom(0, nullptr, 0, 0, &addr, &len); };
501   ExpectRealtimeDeath(Func, "recvfrom");
502   ExpectNonRealtimeSurvival(Func);
503 }
504 
505 TEST(TestRtsanInterceptors, RecvmsgOnASocketDiesWhenRealtime) {
506   msghdr msg{};
507   auto Func = [&]() { recvmsg(0, &msg, 0); };
508   ExpectRealtimeDeath(Func, "recvmsg");
509   ExpectNonRealtimeSurvival(Func);
510 }
511 
512 TEST(TestRtsanInterceptors, ShutdownOnASocketDiesWhenRealtime) {
513   auto Func = [&]() { shutdown(0, 0); };
514   ExpectRealtimeDeath(Func, "shutdown");
515   ExpectNonRealtimeSurvival(Func);
516 }
517