84 lines · cpp
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-exception6//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 || SANITIZER_HAIKU18 19#include <dlfcn.h> // for dlsym() and dlvsym()20 21namespace __interception {22 23#if SANITIZER_NETBSD24static 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#endif35 36static void *GetFuncAddr(const char *name, uptr trampoline) {37#if SANITIZER_NETBSD38 // FIXME: Find a better way to handle renames39 if (StrCmp(name, "sigaction"))40 name = "__sigaction14";41#endif42 void *addr = dlsym(RTLD_NEXT, name);43 if (!addr) {44 // If the lookup using RTLD_NEXT failed, the sanitizer runtime library is45 // later in the library search order than the DSO that we are trying to46 // intercept, which means that we cannot intercept this function. We still47 // want the address of the real definition, though, so look it up using48 // 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 59bool 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_NETBSD68static void *GetFuncAddr(const char *name, const char *ver) {69 return dlvsym(RTLD_NEXT, name, ver);70}71 72bool 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_NETBSD79 80} // namespace __interception81 82#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||83 // SANITIZER_SOLARIS || SANITIZER_HAIKU84