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