145
|
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_OPENBSD || 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 wrapper_addr) {
|
|
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 == wrapper_addr)
|
|
54 addr = nullptr;
|
|
55 }
|
|
56 return addr;
|
|
57 }
|
|
58
|
|
59 bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func,
|
|
60 uptr wrapper) {
|
|
61 void *addr = GetFuncAddr(name, wrapper);
|
|
62 *ptr_to_real = (uptr)addr;
|
|
63 return addr && (func == wrapper);
|
|
64 }
|
|
65
|
|
66 // Android and Solaris do not have dlvsym
|
|
67 #if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD
|
|
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 wrapper) {
|
|
74 void *addr = GetFuncAddr(name, ver);
|
|
75 *ptr_to_real = (uptr)addr;
|
|
76 return addr && (func == wrapper);
|
|
77 }
|
|
78 #endif // !SANITIZER_ANDROID
|
|
79
|
|
80 } // namespace __interception
|
|
81
|
|
82 #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD ||
|
|
83 // SANITIZER_OPENBSD || SANITIZER_SOLARIS
|