246 lines · cpp
1//===-- tysan_interceptors.cpp --------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of TypeSanitizer.10//11// Interceptors for standard library functions.12//===----------------------------------------------------------------------===//13 14#include "interception/interception.h"15#include "sanitizer_common/sanitizer_allocator_dlsym.h"16#include "sanitizer_common/sanitizer_common.h"17#include "tysan/tysan.h"18 19#if SANITIZER_LINUX && !SANITIZER_ANDROID20#define TYSAN_INTERCEPT___STRDUP 121#else22#define TYSAN_INTERCEPT___STRDUP 023#endif24 25#if SANITIZER_LINUX26extern "C" int mallopt(int param, int value);27#endif28 29using namespace __sanitizer;30using namespace __tysan;31 32namespace {33struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {34 static bool UseImpl() { return !tysan_inited; }35};36} // namespace37 38INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {39 if (!tysan_inited && REAL(memset) == nullptr)40 return internal_memset(dst, v, size);41 42 void *res = REAL(memset)(dst, v, size);43 tysan_set_type_unknown(dst, size);44 return res;45}46 47INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {48 if (!tysan_inited && REAL(memmove) == nullptr)49 return internal_memmove(dst, src, size);50 51 void *res = REAL(memmove)(dst, src, size);52 tysan_copy_types(dst, src, size);53 return res;54}55 56INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {57 if (!tysan_inited && REAL(memcpy) == nullptr) {58 // memmove is used here because on some platforms this will also59 // intercept the memmove implementation.60 return internal_memmove(dst, src, size);61 }62 63 void *res = REAL(memcpy)(dst, src, size);64 tysan_copy_types(dst, src, size);65 return res;66}67 68INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,69 int fd, OFF_T offset) {70 void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);71 if (res != (void *)-1)72 tysan_set_type_unknown(res, RoundUpTo(length, GetPageSize()));73 return res;74}75 76#if !SANITIZER_APPLE77INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,78 int fd, OFF64_T offset) {79 void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);80 if (res != (void *)-1)81 tysan_set_type_unknown(res, RoundUpTo(length, GetPageSize()));82 return res;83}84#endif85 86INTERCEPTOR(char *, strdup, const char *s) {87 char *res = REAL(strdup)(s);88 if (res)89 tysan_copy_types(res, const_cast<char *>(s), internal_strlen(s));90 return res;91}92 93#if TYSAN_INTERCEPT___STRDUP94INTERCEPTOR(char *, __strdup, const char *s) {95 char *res = REAL(__strdup)(s);96 if (res)97 tysan_copy_types(res, const_cast<char *>(s), internal_strlen(s));98 return res;99}100#endif // TYSAN_INTERCEPT___STRDUP101 102INTERCEPTOR(void *, malloc, uptr size) {103 if (DlsymAlloc::Use())104 return DlsymAlloc::Allocate(size);105 void *res = REAL(malloc)(size);106 if (res)107 tysan_set_type_unknown(res, size);108 return res;109}110 111#if SANITIZER_APPLE112INTERCEPTOR(uptr, malloc_size, void *ptr) {113 if (DlsymAlloc::PointerIsMine(ptr))114 return DlsymAlloc::GetSize(ptr);115 return REAL(malloc_size)(ptr);116}117#endif118 119INTERCEPTOR(void *, realloc, void *ptr, uptr size) {120 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))121 return DlsymAlloc::Realloc(ptr, size);122 void *res = REAL(realloc)(ptr, size);123 // We might want to copy the types from the original allocation (although124 // that would require that we knew its size).125 if (res)126 tysan_set_type_unknown(res, size);127 return res;128}129 130INTERCEPTOR(void *, calloc, uptr nmemb, uptr size) {131 if (DlsymAlloc::Use())132 return DlsymAlloc::Callocate(nmemb, size);133 void *res = REAL(calloc)(nmemb, size);134 if (res)135 tysan_set_type_unknown(res, nmemb * size);136 return res;137}138 139INTERCEPTOR(void, free, void *ptr) {140 if (DlsymAlloc::PointerIsMine(ptr))141 return DlsymAlloc::Free(ptr);142 REAL(free)(ptr);143}144 145INTERCEPTOR(void *, valloc, uptr size) {146 void *res = REAL(valloc)(size);147 if (res)148 tysan_set_type_unknown(res, size);149 return res;150}151 152#if SANITIZER_INTERCEPT_MEMALIGN153INTERCEPTOR(void *, memalign, uptr alignment, uptr size) {154 void *res = REAL(memalign)(alignment, size);155 if (res)156 tysan_set_type_unknown(res, size);157 return res;158}159#define TYSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)160#else161#define TYSAN_MAYBE_INTERCEPT_MEMALIGN162#endif // SANITIZER_INTERCEPT_MEMALIGN163 164#if SANITIZER_INTERCEPT___LIBC_MEMALIGN165INTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) {166 void *res = REAL(__libc_memalign)(alignment, size);167 if (res)168 tysan_set_type_unknown(res, size);169 return res;170}171#define TYSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN \172 INTERCEPT_FUNCTION(__libc_memalign)173#else174#define TYSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN175#endif // SANITIZER_INTERCEPT___LIBC_MEMALIGN176 177#if SANITIZER_INTERCEPT_PVALLOC178INTERCEPTOR(void *, pvalloc, uptr size) {179 void *res = REAL(pvalloc)(size);180 if (res)181 tysan_set_type_unknown(res, size);182 return res;183}184#define TYSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)185#else186#define TYSAN_MAYBE_INTERCEPT_PVALLOC187#endif // SANITIZER_INTERCEPT_PVALLOC188 189#if SANITIZER_INTERCEPT_ALIGNED_ALLOC190INTERCEPTOR(void *, aligned_alloc, uptr alignment, uptr size) {191 void *res = REAL(aligned_alloc)(alignment, size);192 if (res)193 tysan_set_type_unknown(res, size);194 return res;195}196#define TYSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc)197#else198#define TYSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC199#endif200 201INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {202 int res = REAL(posix_memalign)(memptr, alignment, size);203 if (res == 0 && *memptr)204 tysan_set_type_unknown(*memptr, size);205 return res;206}207 208namespace __tysan {209void InitializeInterceptors() {210 static int inited = 0;211 CHECK_EQ(inited, 0);212 213 // Instruct libc malloc to consume less memory.214#if SANITIZER_LINUX215 mallopt(1, 0); // M_MXFAST216 mallopt(-3, 32 * 1024); // M_MMAP_THRESHOLD217#endif218 219 INTERCEPT_FUNCTION(mmap);220 221 INTERCEPT_FUNCTION(mmap64);222 223 INTERCEPT_FUNCTION(strdup);224#if TYSAN_INTERCEPT___STRDUP225 INTERCEPT_FUNCTION(__strdup);226#endif227 228 INTERCEPT_FUNCTION(malloc);229 INTERCEPT_FUNCTION(calloc);230 INTERCEPT_FUNCTION(free);231 INTERCEPT_FUNCTION(realloc);232 INTERCEPT_FUNCTION(valloc);233 TYSAN_MAYBE_INTERCEPT_MEMALIGN;234 TYSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN;235 TYSAN_MAYBE_INTERCEPT_PVALLOC;236 TYSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC237 INTERCEPT_FUNCTION(posix_memalign);238 239 INTERCEPT_FUNCTION(memset);240 INTERCEPT_FUNCTION(memmove);241 INTERCEPT_FUNCTION(memcpy);242 243 inited = 1;244}245} // namespace __tysan246