Path: blob/main/contrib/llvm-project/compiler-rt/lib/rtsan/rtsan_interceptors.cpp
35233 views
//===--- rtsan_interceptors.cpp - Realtime Sanitizer ------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8//===----------------------------------------------------------------------===//910#include "rtsan/rtsan_interceptors.h"1112#include "interception/interception.h"13#include "sanitizer_common/sanitizer_allocator_dlsym.h"14#include "sanitizer_common/sanitizer_allocator_internal.h"15#include "sanitizer_common/sanitizer_platform.h"16#include "sanitizer_common/sanitizer_platform_interceptors.h"1718#include "interception/interception.h"19#include "rtsan/rtsan.h"20#include "rtsan/rtsan_context.h"2122#if SANITIZER_APPLE2324#if TARGET_OS_MAC25// On MacOS OSSpinLockLock is deprecated and no longer present in the headers,26// but the symbol still exists on the system. Forward declare here so we27// don't get compilation errors.28#include <stdint.h>29extern "C" {30typedef int32_t OSSpinLock;31void OSSpinLockLock(volatile OSSpinLock *__lock);32}33#endif3435#include <libkern/OSAtomic.h>36#include <os/lock.h>37#endif3839#if SANITIZER_INTERCEPT_MEMALIGN || SANITIZER_INTERCEPT_PVALLOC40#include <malloc.h>41#endif4243#include <fcntl.h>44#include <pthread.h>45#include <stdarg.h>46#include <stdio.h>47#include <sys/socket.h>48#include <time.h>49#include <unistd.h>5051using namespace __sanitizer;5253using __rtsan::rtsan_init_is_running;54using __rtsan::rtsan_initialized;5556namespace {57struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {58static bool UseImpl() { return !rtsan_initialized; }59};60} // namespace6162void ExpectNotRealtime(const char *intercepted_function_name) {63__rtsan::GetContextForThisThread().ExpectNotRealtime(64intercepted_function_name);65}6667// Filesystem6869INTERCEPTOR(int, open, const char *path, int oflag, ...) {70// TODO Establish whether we should intercept here if the flag contains71// O_NONBLOCK72ExpectNotRealtime("open");7374va_list args;75va_start(args, oflag);76const mode_t mode = va_arg(args, int);77va_end(args);7879const int result = REAL(open)(path, oflag, mode);80return result;81}8283INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) {84// TODO Establish whether we should intercept here if the flag contains85// O_NONBLOCK86ExpectNotRealtime("openat");8788va_list args;89va_start(args, oflag);90mode_t mode = va_arg(args, int);91va_end(args);9293const int result = REAL(openat)(fd, path, oflag, mode);94return result;95}9697INTERCEPTOR(int, creat, const char *path, mode_t mode) {98// TODO Establish whether we should intercept here if the flag contains99// O_NONBLOCK100ExpectNotRealtime("creat");101const int result = REAL(creat)(path, mode);102return result;103}104105INTERCEPTOR(int, fcntl, int filedes, int cmd, ...) {106ExpectNotRealtime("fcntl");107108va_list args;109va_start(args, cmd);110111// Following precedent here. The linux source (fcntl.c, do_fcntl) accepts the112// final argument in a variable that will hold the largest of the possible113// argument types (pointers and ints are typical in fcntl) It is then assumed114// that the implementation of fcntl will cast it properly depending on cmd.115//116// This is also similar to what is done in117// sanitizer_common/sanitizer_common_syscalls.inc118const unsigned long arg = va_arg(args, unsigned long);119int result = REAL(fcntl)(filedes, cmd, arg);120121va_end(args);122123return result;124}125126INTERCEPTOR(int, close, int filedes) {127ExpectNotRealtime("close");128return REAL(close)(filedes);129}130131INTERCEPTOR(FILE *, fopen, const char *path, const char *mode) {132ExpectNotRealtime("fopen");133return REAL(fopen)(path, mode);134}135136INTERCEPTOR(size_t, fread, void *ptr, size_t size, size_t nitems,137FILE *stream) {138ExpectNotRealtime("fread");139return REAL(fread)(ptr, size, nitems, stream);140}141142INTERCEPTOR(size_t, fwrite, const void *ptr, size_t size, size_t nitems,143FILE *stream) {144ExpectNotRealtime("fwrite");145return REAL(fwrite)(ptr, size, nitems, stream);146}147148INTERCEPTOR(int, fclose, FILE *stream) {149ExpectNotRealtime("fclose");150return REAL(fclose)(stream);151}152153INTERCEPTOR(int, fputs, const char *s, FILE *stream) {154ExpectNotRealtime("fputs");155return REAL(fputs)(s, stream);156}157158// Streams159INTERCEPTOR(int, puts, const char *s) {160ExpectNotRealtime("puts");161return REAL(puts)(s);162}163164// Concurrency165#if SANITIZER_APPLE166#pragma clang diagnostic push167// OSSpinLockLock is deprecated, but still in use in libc++168#pragma clang diagnostic ignored "-Wdeprecated-declarations"169INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) {170ExpectNotRealtime("OSSpinLockLock");171return REAL(OSSpinLockLock)(lock);172}173#pragma clang diagnostic pop174175INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {176ExpectNotRealtime("os_unfair_lock_lock");177return REAL(os_unfair_lock_lock)(lock);178}179#elif SANITIZER_LINUX180INTERCEPTOR(int, pthread_spin_lock, pthread_spinlock_t *spinlock) {181ExpectNotRealtime("pthread_spin_lock");182return REAL(pthread_spin_lock)(spinlock);183}184#endif185186INTERCEPTOR(int, pthread_create, pthread_t *thread, const pthread_attr_t *attr,187void *(*start_routine)(void *), void *arg) {188ExpectNotRealtime("pthread_create");189return REAL(pthread_create)(thread, attr, start_routine, arg);190}191192INTERCEPTOR(int, pthread_mutex_lock, pthread_mutex_t *mutex) {193ExpectNotRealtime("pthread_mutex_lock");194return REAL(pthread_mutex_lock)(mutex);195}196197INTERCEPTOR(int, pthread_mutex_unlock, pthread_mutex_t *mutex) {198ExpectNotRealtime("pthread_mutex_unlock");199return REAL(pthread_mutex_unlock)(mutex);200}201202INTERCEPTOR(int, pthread_join, pthread_t thread, void **value_ptr) {203ExpectNotRealtime("pthread_join");204return REAL(pthread_join)(thread, value_ptr);205}206207INTERCEPTOR(int, pthread_cond_signal, pthread_cond_t *cond) {208ExpectNotRealtime("pthread_cond_signal");209return REAL(pthread_cond_signal)(cond);210}211212INTERCEPTOR(int, pthread_cond_broadcast, pthread_cond_t *cond) {213ExpectNotRealtime("pthread_cond_broadcast");214return REAL(pthread_cond_broadcast)(cond);215}216217INTERCEPTOR(int, pthread_cond_wait, pthread_cond_t *cond,218pthread_mutex_t *mutex) {219ExpectNotRealtime("pthread_cond_wait");220return REAL(pthread_cond_wait)(cond, mutex);221}222223INTERCEPTOR(int, pthread_cond_timedwait, pthread_cond_t *cond,224pthread_mutex_t *mutex, const timespec *ts) {225ExpectNotRealtime("pthread_cond_timedwait");226return REAL(pthread_cond_timedwait)(cond, mutex, ts);227}228229INTERCEPTOR(int, pthread_rwlock_rdlock, pthread_rwlock_t *lock) {230ExpectNotRealtime("pthread_rwlock_rdlock");231return REAL(pthread_rwlock_rdlock)(lock);232}233234INTERCEPTOR(int, pthread_rwlock_unlock, pthread_rwlock_t *lock) {235ExpectNotRealtime("pthread_rwlock_unlock");236return REAL(pthread_rwlock_unlock)(lock);237}238239INTERCEPTOR(int, pthread_rwlock_wrlock, pthread_rwlock_t *lock) {240ExpectNotRealtime("pthread_rwlock_wrlock");241return REAL(pthread_rwlock_wrlock)(lock);242}243244// Sleeping245246INTERCEPTOR(unsigned int, sleep, unsigned int s) {247ExpectNotRealtime("sleep");248return REAL(sleep)(s);249}250251INTERCEPTOR(int, usleep, useconds_t u) {252ExpectNotRealtime("usleep");253return REAL(usleep)(u);254}255256INTERCEPTOR(int, nanosleep, const struct timespec *rqtp,257struct timespec *rmtp) {258ExpectNotRealtime("nanosleep");259return REAL(nanosleep)(rqtp, rmtp);260}261262// Memory263264INTERCEPTOR(void *, calloc, SIZE_T num, SIZE_T size) {265if (DlsymAlloc::Use())266return DlsymAlloc::Callocate(num, size);267268ExpectNotRealtime("calloc");269return REAL(calloc)(num, size);270}271272INTERCEPTOR(void, free, void *ptr) {273if (DlsymAlloc::PointerIsMine(ptr))274return DlsymAlloc::Free(ptr);275276if (ptr != NULL) {277ExpectNotRealtime("free");278}279return REAL(free)(ptr);280}281282INTERCEPTOR(void *, malloc, SIZE_T size) {283if (DlsymAlloc::Use())284return DlsymAlloc::Allocate(size);285286ExpectNotRealtime("malloc");287return REAL(malloc)(size);288}289290INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {291if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))292return DlsymAlloc::Realloc(ptr, size);293294ExpectNotRealtime("realloc");295return REAL(realloc)(ptr, size);296}297298INTERCEPTOR(void *, reallocf, void *ptr, SIZE_T size) {299ExpectNotRealtime("reallocf");300return REAL(reallocf)(ptr, size);301}302303INTERCEPTOR(void *, valloc, SIZE_T size) {304ExpectNotRealtime("valloc");305return REAL(valloc)(size);306}307308#if SANITIZER_INTERCEPT_ALIGNED_ALLOC309INTERCEPTOR(void *, aligned_alloc, SIZE_T alignment, SIZE_T size) {310ExpectNotRealtime("aligned_alloc");311return REAL(aligned_alloc)(alignment, size);312}313#define RTSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc)314#else315#define RTSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC316#endif317318INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) {319ExpectNotRealtime("posix_memalign");320return REAL(posix_memalign)(memptr, alignment, size);321}322323#if SANITIZER_INTERCEPT_MEMALIGN324INTERCEPTOR(void *, memalign, size_t alignment, size_t size) {325ExpectNotRealtime("memalign");326return REAL(memalign)(alignment, size);327}328#endif329330#if SANITIZER_INTERCEPT_PVALLOC331INTERCEPTOR(void *, pvalloc, size_t size) {332ExpectNotRealtime("pvalloc");333return REAL(pvalloc)(size);334}335#endif336337// Sockets338INTERCEPTOR(int, socket, int domain, int type, int protocol) {339ExpectNotRealtime("socket");340return REAL(socket)(domain, type, protocol);341}342343INTERCEPTOR(ssize_t, send, int sockfd, const void *buf, size_t len, int flags) {344ExpectNotRealtime("send");345return REAL(send)(sockfd, buf, len, flags);346}347348INTERCEPTOR(ssize_t, sendmsg, int socket, const struct msghdr *message,349int flags) {350ExpectNotRealtime("sendmsg");351return REAL(sendmsg)(socket, message, flags);352}353354INTERCEPTOR(ssize_t, sendto, int socket, const void *buffer, size_t length,355int flags, const struct sockaddr *dest_addr, socklen_t dest_len) {356ExpectNotRealtime("sendto");357return REAL(sendto)(socket, buffer, length, flags, dest_addr, dest_len);358}359360INTERCEPTOR(ssize_t, recv, int socket, void *buffer, size_t length, int flags) {361ExpectNotRealtime("recv");362return REAL(recv)(socket, buffer, length, flags);363}364365INTERCEPTOR(ssize_t, recvfrom, int socket, void *buffer, size_t length,366int flags, struct sockaddr *address, socklen_t *address_len) {367ExpectNotRealtime("recvfrom");368return REAL(recvfrom)(socket, buffer, length, flags, address, address_len);369}370371INTERCEPTOR(ssize_t, recvmsg, int socket, struct msghdr *message, int flags) {372ExpectNotRealtime("recvmsg");373return REAL(recvmsg)(socket, message, flags);374}375376INTERCEPTOR(int, shutdown, int socket, int how) {377ExpectNotRealtime("shutdown");378return REAL(shutdown)(socket, how);379}380381// Preinit382void __rtsan::InitializeInterceptors() {383INTERCEPT_FUNCTION(calloc);384INTERCEPT_FUNCTION(free);385INTERCEPT_FUNCTION(malloc);386INTERCEPT_FUNCTION(realloc);387INTERCEPT_FUNCTION(reallocf);388INTERCEPT_FUNCTION(valloc);389RTSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC;390INTERCEPT_FUNCTION(posix_memalign);391#if SANITIZER_INTERCEPT_MEMALIGN392INTERCEPT_FUNCTION(memalign);393#endif394#if SANITIZER_INTERCEPT_PVALLOC395INTERCEPT_FUNCTION(pvalloc);396#endif397398INTERCEPT_FUNCTION(open);399INTERCEPT_FUNCTION(openat);400INTERCEPT_FUNCTION(close);401INTERCEPT_FUNCTION(fopen);402INTERCEPT_FUNCTION(fread);403INTERCEPT_FUNCTION(fwrite);404INTERCEPT_FUNCTION(fclose);405INTERCEPT_FUNCTION(fcntl);406INTERCEPT_FUNCTION(creat);407INTERCEPT_FUNCTION(puts);408INTERCEPT_FUNCTION(fputs);409410#if SANITIZER_APPLE411INTERCEPT_FUNCTION(OSSpinLockLock);412INTERCEPT_FUNCTION(os_unfair_lock_lock);413#elif SANITIZER_LINUX414INTERCEPT_FUNCTION(pthread_spin_lock);415#endif416417INTERCEPT_FUNCTION(pthread_create);418INTERCEPT_FUNCTION(pthread_mutex_lock);419INTERCEPT_FUNCTION(pthread_mutex_unlock);420INTERCEPT_FUNCTION(pthread_join);421INTERCEPT_FUNCTION(pthread_cond_signal);422INTERCEPT_FUNCTION(pthread_cond_broadcast);423INTERCEPT_FUNCTION(pthread_cond_wait);424INTERCEPT_FUNCTION(pthread_cond_timedwait);425INTERCEPT_FUNCTION(pthread_rwlock_rdlock);426INTERCEPT_FUNCTION(pthread_rwlock_unlock);427INTERCEPT_FUNCTION(pthread_rwlock_wrlock);428429INTERCEPT_FUNCTION(sleep);430INTERCEPT_FUNCTION(usleep);431INTERCEPT_FUNCTION(nanosleep);432433INTERCEPT_FUNCTION(socket);434INTERCEPT_FUNCTION(send);435INTERCEPT_FUNCTION(sendmsg);436INTERCEPT_FUNCTION(sendto);437INTERCEPT_FUNCTION(recv);438INTERCEPT_FUNCTION(recvmsg);439INTERCEPT_FUNCTION(recvfrom);440INTERCEPT_FUNCTION(shutdown);441}442443444