215 lines · cpp
1//===-- dfsan_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 DataFlowSanitizer.10//11// Interceptors for standard library functions.12//===----------------------------------------------------------------------===//13 14#include <sys/syscall.h>15#include <unistd.h>16 17#include "dfsan/dfsan.h"18#include "dfsan/dfsan_thread.h"19#include "interception/interception.h"20#include "sanitizer_common/sanitizer_allocator_dlsym.h"21#include "sanitizer_common/sanitizer_allocator_interface.h"22#include "sanitizer_common/sanitizer_common.h"23#include "sanitizer_common/sanitizer_errno.h"24#include "sanitizer_common/sanitizer_platform_limits_posix.h"25#include "sanitizer_common/sanitizer_posix.h"26#include "sanitizer_common/sanitizer_tls_get_addr.h"27 28using namespace __dfsan;29using namespace __sanitizer;30 31static bool interceptors_initialized;32 33struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {34 static bool UseImpl() { return !dfsan_inited; }35};36 37INTERCEPTOR(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size) {38 return dfsan_reallocarray(ptr, nmemb, size);39}40 41INTERCEPTOR(void *, __libc_memalign, SIZE_T alignment, SIZE_T size) {42 return dfsan_memalign(alignment, size);43}44 45INTERCEPTOR(void *, aligned_alloc, SIZE_T alignment, SIZE_T size) {46 return dfsan_aligned_alloc(alignment, size);47}48 49INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {50 if (DlsymAlloc::Use())51 return DlsymAlloc::Callocate(nmemb, size);52 return dfsan_calloc(nmemb, size);53}54 55INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {56 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))57 return DlsymAlloc::Realloc(ptr, size);58 return dfsan_realloc(ptr, size);59}60 61INTERCEPTOR(void *, malloc, SIZE_T size) {62 if (DlsymAlloc::Use())63 return DlsymAlloc::Allocate(size);64 return dfsan_malloc(size);65}66 67INTERCEPTOR(void, free, void *ptr) {68 if (!ptr)69 return;70 if (DlsymAlloc::PointerIsMine(ptr))71 return DlsymAlloc::Free(ptr);72 return dfsan_deallocate(ptr);73}74 75INTERCEPTOR(void, cfree, void *ptr) {76 if (!ptr)77 return;78 if (DlsymAlloc::PointerIsMine(ptr))79 return DlsymAlloc::Free(ptr);80 return dfsan_deallocate(ptr);81}82 83INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {84 CHECK_NE(memptr, 0);85 int res = dfsan_posix_memalign(memptr, alignment, size);86 if (!res)87 dfsan_set_label(0, memptr, sizeof(*memptr));88 return res;89}90 91INTERCEPTOR(void *, memalign, SIZE_T alignment, SIZE_T size) {92 return dfsan_memalign(alignment, size);93}94 95INTERCEPTOR(void *, valloc, SIZE_T size) { return dfsan_valloc(size); }96 97INTERCEPTOR(void *, pvalloc, SIZE_T size) { return dfsan_pvalloc(size); }98 99INTERCEPTOR(void, mallinfo, __sanitizer_struct_mallinfo *sret) {100 internal_memset(sret, 0, sizeof(*sret));101 dfsan_set_label(0, sret, sizeof(*sret));102}103 104INTERCEPTOR(int, mallopt, int cmd, int value) { return 0; }105 106INTERCEPTOR(void, malloc_stats, void) {107 // FIXME: implement, but don't call REAL(malloc_stats)!108}109 110INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {111 return __sanitizer_get_allocated_size(ptr);112}113 114#define ENSURE_DFSAN_INITED() \115 do { \116 CHECK(!dfsan_init_is_running); \117 if (!dfsan_inited) { \118 dfsan_init(); \119 } \120 } while (0)121 122#define COMMON_INTERCEPTOR_ENTER(func, ...) \123 if (dfsan_init_is_running) \124 return REAL(func)(__VA_ARGS__); \125 ENSURE_DFSAN_INITED(); \126 dfsan_set_label(0, __errno_location(), sizeof(int));127 128INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,129 int fd, OFF_T offset) {130 if (common_flags()->detect_write_exec)131 ReportMmapWriteExec(prot, flags);132 if (!dfsan_inited)133 return (void *)internal_mmap(addr, length, prot, flags, fd, offset);134 COMMON_INTERCEPTOR_ENTER(mmap, addr, length, prot, flags, fd, offset);135 void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);136 if (res != (void *)-1) {137 dfsan_set_label(0, res, RoundUpTo(length, GetPageSizeCached()));138 }139 return res;140}141 142INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,143 int fd, OFF64_T offset) {144 if (common_flags()->detect_write_exec)145 ReportMmapWriteExec(prot, flags);146 if (!dfsan_inited)147 return (void *)internal_mmap(addr, length, prot, flags, fd, offset);148 COMMON_INTERCEPTOR_ENTER(mmap64, addr, length, prot, flags, fd, offset);149 void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);150 if (res != (void *)-1) {151 dfsan_set_label(0, res, RoundUpTo(length, GetPageSizeCached()));152 }153 return res;154}155 156INTERCEPTOR(int, munmap, void *addr, SIZE_T length) {157 if (!dfsan_inited)158 return internal_munmap(addr, length);159 COMMON_INTERCEPTOR_ENTER(munmap, addr, length);160 int res = REAL(munmap)(addr, length);161 if (res != -1)162 dfsan_set_label(0, addr, RoundUpTo(length, GetPageSizeCached()));163 return res;164}165 166#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \167 if (DFsanThread *t = GetCurrentThread()) { \168 *begin = t->tls_begin(); \169 *end = t->tls_end(); \170 } else { \171 *begin = *end = 0; \172 }173#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \174 dfsan_set_label(0, ptr, size)175 176INTERCEPTOR(void *, __tls_get_addr, void *arg) {177 COMMON_INTERCEPTOR_ENTER(__tls_get_addr, arg);178 void *res = REAL(__tls_get_addr)(arg);179 uptr tls_begin, tls_end;180 COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);181 DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, tls_begin, tls_end);182 if (dtv) {183 // New DTLS block has been allocated.184 COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);185 }186 return res;187}188 189void __dfsan::initialize_interceptors() {190 CHECK(!interceptors_initialized);191 192 INTERCEPT_FUNCTION(aligned_alloc);193 INTERCEPT_FUNCTION(calloc);194 INTERCEPT_FUNCTION(cfree);195 INTERCEPT_FUNCTION(free);196 INTERCEPT_FUNCTION(mallinfo);197 INTERCEPT_FUNCTION(malloc);198 INTERCEPT_FUNCTION(malloc_stats);199 INTERCEPT_FUNCTION(malloc_usable_size);200 INTERCEPT_FUNCTION(mallopt);201 INTERCEPT_FUNCTION(memalign);202 INTERCEPT_FUNCTION(mmap);203 INTERCEPT_FUNCTION(mmap64);204 INTERCEPT_FUNCTION(munmap);205 INTERCEPT_FUNCTION(posix_memalign);206 INTERCEPT_FUNCTION(pvalloc);207 INTERCEPT_FUNCTION(realloc);208 INTERCEPT_FUNCTION(reallocarray);209 INTERCEPT_FUNCTION(valloc);210 INTERCEPT_FUNCTION(__tls_get_addr);211 INTERCEPT_FUNCTION(__libc_memalign);212 213 interceptors_initialized = true;214}215