1*ebbce04cSNico Weber //===-- interception_linux.cpp ----------------------------------*- C++ -*-===// 2*ebbce04cSNico Weber // 3*ebbce04cSNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*ebbce04cSNico Weber // See https://llvm.org/LICENSE.txt for license information. 5*ebbce04cSNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*ebbce04cSNico Weber // 7*ebbce04cSNico Weber //===----------------------------------------------------------------------===// 8*ebbce04cSNico Weber // 9*ebbce04cSNico Weber // This file is a part of AddressSanitizer, an address sanity checker. 10*ebbce04cSNico Weber // 11*ebbce04cSNico Weber // Linux-specific interception methods. 12*ebbce04cSNico Weber //===----------------------------------------------------------------------===// 13*ebbce04cSNico Weber 14*ebbce04cSNico Weber #include "interception.h" 15*ebbce04cSNico Weber 16*ebbce04cSNico Weber #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ 17*ebbce04cSNico Weber SANITIZER_OPENBSD || SANITIZER_SOLARIS 18*ebbce04cSNico Weber 19*ebbce04cSNico Weber #include <dlfcn.h> // for dlsym() and dlvsym() 20*ebbce04cSNico Weber 21*ebbce04cSNico Weber namespace __interception { 22*ebbce04cSNico Weber 23*ebbce04cSNico Weber #if SANITIZER_NETBSD 24*ebbce04cSNico Weber static int StrCmp(const char *s1, const char *s2) { 25*ebbce04cSNico Weber while (true) { 26*ebbce04cSNico Weber if (*s1 != *s2) 27*ebbce04cSNico Weber return false; 28*ebbce04cSNico Weber if (*s1 == 0) 29*ebbce04cSNico Weber return true; 30*ebbce04cSNico Weber s1++; 31*ebbce04cSNico Weber s2++; 32*ebbce04cSNico Weber } 33*ebbce04cSNico Weber } 34*ebbce04cSNico Weber #endif 35*ebbce04cSNico Weber 36*ebbce04cSNico Weber static void *GetFuncAddr(const char *name, uptr wrapper_addr) { 37*ebbce04cSNico Weber #if SANITIZER_NETBSD 38*ebbce04cSNico Weber // FIXME: Find a better way to handle renames 39*ebbce04cSNico Weber if (StrCmp(name, "sigaction")) 40*ebbce04cSNico Weber name = "__sigaction14"; 41*ebbce04cSNico Weber #endif 42*ebbce04cSNico Weber void *addr = dlsym(RTLD_NEXT, name); 43*ebbce04cSNico Weber if (!addr) { 44*ebbce04cSNico Weber // If the lookup using RTLD_NEXT failed, the sanitizer runtime library is 45*ebbce04cSNico Weber // later in the library search order than the DSO that we are trying to 46*ebbce04cSNico Weber // intercept, which means that we cannot intercept this function. We still 47*ebbce04cSNico Weber // want the address of the real definition, though, so look it up using 48*ebbce04cSNico Weber // RTLD_DEFAULT. 49*ebbce04cSNico Weber addr = dlsym(RTLD_DEFAULT, name); 50*ebbce04cSNico Weber 51*ebbce04cSNico Weber // In case `name' is not loaded, dlsym ends up finding the actual wrapper. 52*ebbce04cSNico Weber // We don't want to intercept the wrapper and have it point to itself. 53*ebbce04cSNico Weber if ((uptr)addr == wrapper_addr) 54*ebbce04cSNico Weber addr = nullptr; 55*ebbce04cSNico Weber } 56*ebbce04cSNico Weber return addr; 57*ebbce04cSNico Weber } 58*ebbce04cSNico Weber 59*ebbce04cSNico Weber bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func, 60*ebbce04cSNico Weber uptr wrapper) { 61*ebbce04cSNico Weber void *addr = GetFuncAddr(name, wrapper); 62*ebbce04cSNico Weber *ptr_to_real = (uptr)addr; 63*ebbce04cSNico Weber return addr && (func == wrapper); 64*ebbce04cSNico Weber } 65*ebbce04cSNico Weber 66*ebbce04cSNico Weber // Android and Solaris do not have dlvsym 67*ebbce04cSNico Weber #if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD 68*ebbce04cSNico Weber static void *GetFuncAddr(const char *name, const char *ver) { 69*ebbce04cSNico Weber return dlvsym(RTLD_NEXT, name, ver); 70*ebbce04cSNico Weber } 71*ebbce04cSNico Weber 72*ebbce04cSNico Weber bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, 73*ebbce04cSNico Weber uptr func, uptr wrapper) { 74*ebbce04cSNico Weber void *addr = GetFuncAddr(name, ver); 75*ebbce04cSNico Weber *ptr_to_real = (uptr)addr; 76*ebbce04cSNico Weber return addr && (func == wrapper); 77*ebbce04cSNico Weber } 78*ebbce04cSNico Weber #endif // !SANITIZER_ANDROID 79*ebbce04cSNico Weber 80*ebbce04cSNico Weber } // namespace __interception 81*ebbce04cSNico Weber 82*ebbce04cSNico Weber #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || 83*ebbce04cSNico Weber // SANITIZER_OPENBSD || SANITIZER_SOLARIS 84