1 //===--- rtsan_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 "rtsan/rtsan_interceptors.h" 12 13 #include "interception/interception.h" 14 #include "sanitizer_common/sanitizer_allocator_dlsym.h" 15 #include "sanitizer_common/sanitizer_allocator_internal.h" 16 #include "sanitizer_common/sanitizer_platform.h" 17 #include "sanitizer_common/sanitizer_platform_interceptors.h" 18 19 #include "interception/interception.h" 20 #include "rtsan/rtsan.h" 21 #include "rtsan/rtsan_context.h" 22 23 #if SANITIZER_APPLE 24 25 #if TARGET_OS_MAC 26 // On MacOS OSSpinLockLock is deprecated and no longer present in the headers, 27 // but the symbol still exists on the system. Forward declare here so we 28 // don't get compilation errors. 29 #include <stdint.h> 30 extern "C" { 31 typedef int32_t OSSpinLock; 32 void OSSpinLockLock(volatile OSSpinLock *__lock); 33 } 34 #endif 35 36 #include <libkern/OSAtomic.h> 37 #include <os/lock.h> 38 #endif 39 40 #if SANITIZER_INTERCEPT_MEMALIGN || SANITIZER_INTERCEPT_PVALLOC 41 #include <malloc.h> 42 #endif 43 44 #include <fcntl.h> 45 #include <pthread.h> 46 #include <stdarg.h> 47 #include <stdio.h> 48 #include <sys/socket.h> 49 #include <time.h> 50 #include <unistd.h> 51 52 using namespace __sanitizer; 53 54 using __rtsan::rtsan_init_is_running; 55 using __rtsan::rtsan_initialized; 56 57 namespace { 58 struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> { 59 static bool UseImpl() { return !rtsan_initialized; } 60 }; 61 } // namespace 62 63 void ExpectNotRealtime(const char *intercepted_function_name) { 64 __rtsan::GetContextForThisThread().ExpectNotRealtime( 65 intercepted_function_name); 66 } 67 68 // Filesystem 69 70 INTERCEPTOR(int, open, const char *path, int oflag, ...) { 71 // TODO Establish whether we should intercept here if the flag contains 72 // O_NONBLOCK 73 ExpectNotRealtime("open"); 74 75 va_list args; 76 va_start(args, oflag); 77 const mode_t mode = va_arg(args, int); 78 va_end(args); 79 80 const int result = REAL(open)(path, oflag, mode); 81 return result; 82 } 83 84 INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) { 85 // TODO Establish whether we should intercept here if the flag contains 86 // O_NONBLOCK 87 ExpectNotRealtime("openat"); 88 89 va_list args; 90 va_start(args, oflag); 91 mode_t mode = va_arg(args, int); 92 va_end(args); 93 94 const int result = REAL(openat)(fd, path, oflag, mode); 95 return result; 96 } 97 98 INTERCEPTOR(int, creat, const char *path, mode_t mode) { 99 // TODO Establish whether we should intercept here if the flag contains 100 // O_NONBLOCK 101 ExpectNotRealtime("creat"); 102 const int result = REAL(creat)(path, mode); 103 return result; 104 } 105 106 INTERCEPTOR(int, fcntl, int filedes, int cmd, ...) { 107 ExpectNotRealtime("fcntl"); 108 109 va_list args; 110 va_start(args, cmd); 111 112 // Following precedent here. The linux source (fcntl.c, do_fcntl) accepts the 113 // final argument in a variable that will hold the largest of the possible 114 // argument types (pointers and ints are typical in fcntl) It is then assumed 115 // that the implementation of fcntl will cast it properly depending on cmd. 116 // 117 // This is also similar to what is done in 118 // sanitizer_common/sanitizer_common_syscalls.inc 119 const unsigned long arg = va_arg(args, unsigned long); 120 int result = REAL(fcntl)(filedes, cmd, arg); 121 122 va_end(args); 123 124 return result; 125 } 126 127 INTERCEPTOR(int, close, int filedes) { 128 ExpectNotRealtime("close"); 129 return REAL(close)(filedes); 130 } 131 132 INTERCEPTOR(FILE *, fopen, const char *path, const char *mode) { 133 ExpectNotRealtime("fopen"); 134 return REAL(fopen)(path, mode); 135 } 136 137 INTERCEPTOR(size_t, fread, void *ptr, size_t size, size_t nitems, 138 FILE *stream) { 139 ExpectNotRealtime("fread"); 140 return REAL(fread)(ptr, size, nitems, stream); 141 } 142 143 INTERCEPTOR(size_t, fwrite, const void *ptr, size_t size, size_t nitems, 144 FILE *stream) { 145 ExpectNotRealtime("fwrite"); 146 return REAL(fwrite)(ptr, size, nitems, stream); 147 } 148 149 INTERCEPTOR(int, fclose, FILE *stream) { 150 ExpectNotRealtime("fclose"); 151 return REAL(fclose)(stream); 152 } 153 154 INTERCEPTOR(int, fputs, const char *s, FILE *stream) { 155 ExpectNotRealtime("fputs"); 156 return REAL(fputs)(s, stream); 157 } 158 159 // Streams 160 INTERCEPTOR(int, puts, const char *s) { 161 ExpectNotRealtime("puts"); 162 return REAL(puts)(s); 163 } 164 165 // Concurrency 166 #if SANITIZER_APPLE 167 #pragma clang diagnostic push 168 // OSSpinLockLock is deprecated, but still in use in libc++ 169 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 170 INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) { 171 ExpectNotRealtime("OSSpinLockLock"); 172 return REAL(OSSpinLockLock)(lock); 173 } 174 #pragma clang diagnostic pop 175 176 INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) { 177 ExpectNotRealtime("os_unfair_lock_lock"); 178 return REAL(os_unfair_lock_lock)(lock); 179 } 180 #elif SANITIZER_LINUX 181 INTERCEPTOR(int, pthread_spin_lock, pthread_spinlock_t *spinlock) { 182 ExpectNotRealtime("pthread_spin_lock"); 183 return REAL(pthread_spin_lock)(spinlock); 184 } 185 #endif 186 187 INTERCEPTOR(int, pthread_create, pthread_t *thread, const pthread_attr_t *attr, 188 void *(*start_routine)(void *), void *arg) { 189 ExpectNotRealtime("pthread_create"); 190 return REAL(pthread_create)(thread, attr, start_routine, arg); 191 } 192 193 INTERCEPTOR(int, pthread_mutex_lock, pthread_mutex_t *mutex) { 194 ExpectNotRealtime("pthread_mutex_lock"); 195 return REAL(pthread_mutex_lock)(mutex); 196 } 197 198 INTERCEPTOR(int, pthread_mutex_unlock, pthread_mutex_t *mutex) { 199 ExpectNotRealtime("pthread_mutex_unlock"); 200 return REAL(pthread_mutex_unlock)(mutex); 201 } 202 203 INTERCEPTOR(int, pthread_join, pthread_t thread, void **value_ptr) { 204 ExpectNotRealtime("pthread_join"); 205 return REAL(pthread_join)(thread, value_ptr); 206 } 207 208 INTERCEPTOR(int, pthread_cond_signal, pthread_cond_t *cond) { 209 ExpectNotRealtime("pthread_cond_signal"); 210 return REAL(pthread_cond_signal)(cond); 211 } 212 213 INTERCEPTOR(int, pthread_cond_broadcast, pthread_cond_t *cond) { 214 ExpectNotRealtime("pthread_cond_broadcast"); 215 return REAL(pthread_cond_broadcast)(cond); 216 } 217 218 INTERCEPTOR(int, pthread_cond_wait, pthread_cond_t *cond, 219 pthread_mutex_t *mutex) { 220 ExpectNotRealtime("pthread_cond_wait"); 221 return REAL(pthread_cond_wait)(cond, mutex); 222 } 223 224 INTERCEPTOR(int, pthread_cond_timedwait, pthread_cond_t *cond, 225 pthread_mutex_t *mutex, const timespec *ts) { 226 ExpectNotRealtime("pthread_cond_timedwait"); 227 return REAL(pthread_cond_timedwait)(cond, mutex, ts); 228 } 229 230 INTERCEPTOR(int, pthread_rwlock_rdlock, pthread_rwlock_t *lock) { 231 ExpectNotRealtime("pthread_rwlock_rdlock"); 232 return REAL(pthread_rwlock_rdlock)(lock); 233 } 234 235 INTERCEPTOR(int, pthread_rwlock_unlock, pthread_rwlock_t *lock) { 236 ExpectNotRealtime("pthread_rwlock_unlock"); 237 return REAL(pthread_rwlock_unlock)(lock); 238 } 239 240 INTERCEPTOR(int, pthread_rwlock_wrlock, pthread_rwlock_t *lock) { 241 ExpectNotRealtime("pthread_rwlock_wrlock"); 242 return REAL(pthread_rwlock_wrlock)(lock); 243 } 244 245 // Sleeping 246 247 INTERCEPTOR(unsigned int, sleep, unsigned int s) { 248 ExpectNotRealtime("sleep"); 249 return REAL(sleep)(s); 250 } 251 252 INTERCEPTOR(int, usleep, useconds_t u) { 253 ExpectNotRealtime("usleep"); 254 return REAL(usleep)(u); 255 } 256 257 INTERCEPTOR(int, nanosleep, const struct timespec *rqtp, 258 struct timespec *rmtp) { 259 ExpectNotRealtime("nanosleep"); 260 return REAL(nanosleep)(rqtp, rmtp); 261 } 262 263 // Memory 264 265 INTERCEPTOR(void *, calloc, SIZE_T num, SIZE_T size) { 266 if (DlsymAlloc::Use()) 267 return DlsymAlloc::Callocate(num, size); 268 269 ExpectNotRealtime("calloc"); 270 return REAL(calloc)(num, size); 271 } 272 273 INTERCEPTOR(void, free, void *ptr) { 274 if (DlsymAlloc::PointerIsMine(ptr)) 275 return DlsymAlloc::Free(ptr); 276 277 if (ptr != NULL) { 278 ExpectNotRealtime("free"); 279 } 280 return REAL(free)(ptr); 281 } 282 283 INTERCEPTOR(void *, malloc, SIZE_T size) { 284 if (DlsymAlloc::Use()) 285 return DlsymAlloc::Allocate(size); 286 287 ExpectNotRealtime("malloc"); 288 return REAL(malloc)(size); 289 } 290 291 INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) { 292 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr)) 293 return DlsymAlloc::Realloc(ptr, size); 294 295 ExpectNotRealtime("realloc"); 296 return REAL(realloc)(ptr, size); 297 } 298 299 INTERCEPTOR(void *, reallocf, void *ptr, SIZE_T size) { 300 ExpectNotRealtime("reallocf"); 301 return REAL(reallocf)(ptr, size); 302 } 303 304 INTERCEPTOR(void *, valloc, SIZE_T size) { 305 ExpectNotRealtime("valloc"); 306 return REAL(valloc)(size); 307 } 308 309 #if SANITIZER_INTERCEPT_ALIGNED_ALLOC 310 INTERCEPTOR(void *, aligned_alloc, SIZE_T alignment, SIZE_T size) { 311 ExpectNotRealtime("aligned_alloc"); 312 return REAL(aligned_alloc)(alignment, size); 313 } 314 #define RTSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc) 315 #else 316 #define RTSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC 317 #endif 318 319 INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) { 320 ExpectNotRealtime("posix_memalign"); 321 return REAL(posix_memalign)(memptr, alignment, size); 322 } 323 324 #if SANITIZER_INTERCEPT_MEMALIGN 325 INTERCEPTOR(void *, memalign, size_t alignment, size_t size) { 326 ExpectNotRealtime("memalign"); 327 return REAL(memalign)(alignment, size); 328 } 329 #endif 330 331 #if SANITIZER_INTERCEPT_PVALLOC 332 INTERCEPTOR(void *, pvalloc, size_t size) { 333 ExpectNotRealtime("pvalloc"); 334 return REAL(pvalloc)(size); 335 } 336 #endif 337 338 // Sockets 339 INTERCEPTOR(int, socket, int domain, int type, int protocol) { 340 ExpectNotRealtime("socket"); 341 return REAL(socket)(domain, type, protocol); 342 } 343 344 INTERCEPTOR(ssize_t, send, int sockfd, const void *buf, size_t len, int flags) { 345 ExpectNotRealtime("send"); 346 return REAL(send)(sockfd, buf, len, flags); 347 } 348 349 INTERCEPTOR(ssize_t, sendmsg, int socket, const struct msghdr *message, 350 int flags) { 351 ExpectNotRealtime("sendmsg"); 352 return REAL(sendmsg)(socket, message, flags); 353 } 354 355 INTERCEPTOR(ssize_t, sendto, int socket, const void *buffer, size_t length, 356 int flags, const struct sockaddr *dest_addr, socklen_t dest_len) { 357 ExpectNotRealtime("sendto"); 358 return REAL(sendto)(socket, buffer, length, flags, dest_addr, dest_len); 359 } 360 361 INTERCEPTOR(ssize_t, recv, int socket, void *buffer, size_t length, int flags) { 362 ExpectNotRealtime("recv"); 363 return REAL(recv)(socket, buffer, length, flags); 364 } 365 366 INTERCEPTOR(ssize_t, recvfrom, int socket, void *buffer, size_t length, 367 int flags, struct sockaddr *address, socklen_t *address_len) { 368 ExpectNotRealtime("recvfrom"); 369 return REAL(recvfrom)(socket, buffer, length, flags, address, address_len); 370 } 371 372 INTERCEPTOR(ssize_t, recvmsg, int socket, struct msghdr *message, int flags) { 373 ExpectNotRealtime("recvmsg"); 374 return REAL(recvmsg)(socket, message, flags); 375 } 376 377 INTERCEPTOR(int, shutdown, int socket, int how) { 378 ExpectNotRealtime("shutdown"); 379 return REAL(shutdown)(socket, how); 380 } 381 382 // Preinit 383 void __rtsan::InitializeInterceptors() { 384 INTERCEPT_FUNCTION(calloc); 385 INTERCEPT_FUNCTION(free); 386 INTERCEPT_FUNCTION(malloc); 387 INTERCEPT_FUNCTION(realloc); 388 INTERCEPT_FUNCTION(reallocf); 389 INTERCEPT_FUNCTION(valloc); 390 RTSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC; 391 INTERCEPT_FUNCTION(posix_memalign); 392 #if SANITIZER_INTERCEPT_MEMALIGN 393 INTERCEPT_FUNCTION(memalign); 394 #endif 395 #if SANITIZER_INTERCEPT_PVALLOC 396 INTERCEPT_FUNCTION(pvalloc); 397 #endif 398 399 INTERCEPT_FUNCTION(open); 400 INTERCEPT_FUNCTION(openat); 401 INTERCEPT_FUNCTION(close); 402 INTERCEPT_FUNCTION(fopen); 403 INTERCEPT_FUNCTION(fread); 404 INTERCEPT_FUNCTION(fwrite); 405 INTERCEPT_FUNCTION(fclose); 406 INTERCEPT_FUNCTION(fcntl); 407 INTERCEPT_FUNCTION(creat); 408 INTERCEPT_FUNCTION(puts); 409 INTERCEPT_FUNCTION(fputs); 410 411 #if SANITIZER_APPLE 412 INTERCEPT_FUNCTION(OSSpinLockLock); 413 INTERCEPT_FUNCTION(os_unfair_lock_lock); 414 #elif SANITIZER_LINUX 415 INTERCEPT_FUNCTION(pthread_spin_lock); 416 #endif 417 418 INTERCEPT_FUNCTION(pthread_create); 419 INTERCEPT_FUNCTION(pthread_mutex_lock); 420 INTERCEPT_FUNCTION(pthread_mutex_unlock); 421 INTERCEPT_FUNCTION(pthread_join); 422 INTERCEPT_FUNCTION(pthread_cond_signal); 423 INTERCEPT_FUNCTION(pthread_cond_broadcast); 424 INTERCEPT_FUNCTION(pthread_cond_wait); 425 INTERCEPT_FUNCTION(pthread_cond_timedwait); 426 INTERCEPT_FUNCTION(pthread_rwlock_rdlock); 427 INTERCEPT_FUNCTION(pthread_rwlock_unlock); 428 INTERCEPT_FUNCTION(pthread_rwlock_wrlock); 429 430 INTERCEPT_FUNCTION(sleep); 431 INTERCEPT_FUNCTION(usleep); 432 INTERCEPT_FUNCTION(nanosleep); 433 434 INTERCEPT_FUNCTION(socket); 435 INTERCEPT_FUNCTION(send); 436 INTERCEPT_FUNCTION(sendmsg); 437 INTERCEPT_FUNCTION(sendto); 438 INTERCEPT_FUNCTION(recv); 439 INTERCEPT_FUNCTION(recvmsg); 440 INTERCEPT_FUNCTION(recvfrom); 441 INTERCEPT_FUNCTION(shutdown); 442 } 443