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