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