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