| 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 | |