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