xref: /aosp_15_r20/external/compiler-rt/lib/esan/esan_interceptors.cpp (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
1*7c3d14c8STreehugger Robot //===-- esan_interceptors.cpp ---------------------------------------------===//
2*7c3d14c8STreehugger Robot //
3*7c3d14c8STreehugger Robot //                     The LLVM Compiler Infrastructure
4*7c3d14c8STreehugger Robot //
5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source
6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details.
7*7c3d14c8STreehugger Robot //
8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
9*7c3d14c8STreehugger Robot //
10*7c3d14c8STreehugger Robot // This file is a part of EfficiencySanitizer, a family of performance tuners.
11*7c3d14c8STreehugger Robot //
12*7c3d14c8STreehugger Robot // Interception routines for the esan run-time.
13*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
14*7c3d14c8STreehugger Robot 
15*7c3d14c8STreehugger Robot #include "esan.h"
16*7c3d14c8STreehugger Robot #include "esan_shadow.h"
17*7c3d14c8STreehugger Robot #include "interception/interception.h"
18*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_common.h"
19*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_libc.h"
20*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_linux.h"
21*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_stacktrace.h"
22*7c3d14c8STreehugger Robot 
23*7c3d14c8STreehugger Robot using namespace __esan; // NOLINT
24*7c3d14c8STreehugger Robot 
25*7c3d14c8STreehugger Robot #define CUR_PC() (StackTrace::GetCurrentPc())
26*7c3d14c8STreehugger Robot 
27*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
28*7c3d14c8STreehugger Robot // Interception via sanitizer common interceptors
29*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
30*7c3d14c8STreehugger Robot 
31*7c3d14c8STreehugger Robot // Get the per-platform defines for what is possible to intercept
32*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_platform_interceptors.h"
33*7c3d14c8STreehugger Robot 
34*7c3d14c8STreehugger Robot // TODO(bruening): tsan disables several interceptors (getpwent, etc.) claiming
35*7c3d14c8STreehugger Robot // that interception is a perf hit: should we do the same?
36*7c3d14c8STreehugger Robot 
37*7c3d14c8STreehugger Robot // We have no need to intercept:
38*7c3d14c8STreehugger Robot #undef SANITIZER_INTERCEPT_TLS_GET_ADDR
39*7c3d14c8STreehugger Robot 
40*7c3d14c8STreehugger Robot // TODO(bruening): the common realpath interceptor assumes malloc is
41*7c3d14c8STreehugger Robot // intercepted!  We should try to parametrize that, though we'll
42*7c3d14c8STreehugger Robot // intercept malloc soon ourselves and can then remove this undef.
43*7c3d14c8STreehugger Robot #undef SANITIZER_INTERCEPT_REALPATH
44*7c3d14c8STreehugger Robot 
45*7c3d14c8STreehugger Robot // We provide our own version:
46*7c3d14c8STreehugger Robot #undef SANITIZER_INTERCEPT_SIGPROCMASK
47*7c3d14c8STreehugger Robot 
48*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!EsanIsInitialized)
49*7c3d14c8STreehugger Robot 
50*7c3d14c8STreehugger Robot #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
51*7c3d14c8STreehugger Robot #define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                          \
52*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION_VER(name, ver)
53*7c3d14c8STreehugger Robot 
54*7c3d14c8STreehugger Robot // We must initialize during early interceptors, to support tcmalloc.
55*7c3d14c8STreehugger Robot // This means that for some apps we fully initialize prior to
56*7c3d14c8STreehugger Robot // __esan_init() being called.
57*7c3d14c8STreehugger Robot // We currently do not use ctx.
58*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                               \
59*7c3d14c8STreehugger Robot   do {                                                                         \
60*7c3d14c8STreehugger Robot     if (UNLIKELY(COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)) {                 \
61*7c3d14c8STreehugger Robot       if (!UNLIKELY(EsanDuringInit))                                           \
62*7c3d14c8STreehugger Robot         initializeLibrary(__esan_which_tool);                                  \
63*7c3d14c8STreehugger Robot       return REAL(func)(__VA_ARGS__);                                          \
64*7c3d14c8STreehugger Robot     }                                                                          \
65*7c3d14c8STreehugger Robot     ctx = nullptr;                                                             \
66*7c3d14c8STreehugger Robot     (void)ctx;                                                                 \
67*7c3d14c8STreehugger Robot   } while (false)
68*7c3d14c8STreehugger Robot 
69*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, func, ...)                      \
70*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, func, __VA_ARGS__)
71*7c3d14c8STreehugger Robot 
72*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size)                         \
73*7c3d14c8STreehugger Robot   processRangeAccess(CUR_PC(), (uptr)ptr, size, true)
74*7c3d14c8STreehugger Robot 
75*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size)                          \
76*7c3d14c8STreehugger Robot   processRangeAccess(CUR_PC(), (uptr)ptr, size, false)
77*7c3d14c8STreehugger Robot 
78*7c3d14c8STreehugger Robot // This is only called if the app explicitly calls exit(), not on
79*7c3d14c8STreehugger Robot // a normal exit.
80*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_ON_EXIT(ctx) finalizeLibrary()
81*7c3d14c8STreehugger Robot 
82*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path)                          \
83*7c3d14c8STreehugger Robot   do {                                                                         \
84*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
85*7c3d14c8STreehugger Robot     (void)(file);                                                              \
86*7c3d14c8STreehugger Robot     (void)(path);                                                              \
87*7c3d14c8STreehugger Robot   } while (false)
88*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file)                               \
89*7c3d14c8STreehugger Robot   do {                                                                         \
90*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
91*7c3d14c8STreehugger Robot     (void)(file);                                                              \
92*7c3d14c8STreehugger Robot   } while (false)
93*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)                    \
94*7c3d14c8STreehugger Robot   do {                                                                         \
95*7c3d14c8STreehugger Robot     (void)(filename);                                                          \
96*7c3d14c8STreehugger Robot     (void)(handle);                                                            \
97*7c3d14c8STreehugger Robot   } while (false)
98*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED()                                  \
99*7c3d14c8STreehugger Robot   do {                                                                         \
100*7c3d14c8STreehugger Robot   } while (false)
101*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_ACQUIRE(ctx, u)                                     \
102*7c3d14c8STreehugger Robot   do {                                                                         \
103*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
104*7c3d14c8STreehugger Robot     (void)(u);                                                                 \
105*7c3d14c8STreehugger Robot   } while (false)
106*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_RELEASE(ctx, u)                                     \
107*7c3d14c8STreehugger Robot   do {                                                                         \
108*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
109*7c3d14c8STreehugger Robot     (void)(u);                                                                 \
110*7c3d14c8STreehugger Robot   } while (false)
111*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path)                              \
112*7c3d14c8STreehugger Robot   do {                                                                         \
113*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
114*7c3d14c8STreehugger Robot     (void)(path);                                                              \
115*7c3d14c8STreehugger Robot   } while (false)
116*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd)                                 \
117*7c3d14c8STreehugger Robot   do {                                                                         \
118*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
119*7c3d14c8STreehugger Robot     (void)(fd);                                                                \
120*7c3d14c8STreehugger Robot   } while (false)
121*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd)                                 \
122*7c3d14c8STreehugger Robot   do {                                                                         \
123*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
124*7c3d14c8STreehugger Robot     (void)(fd);                                                                \
125*7c3d14c8STreehugger Robot   } while (false)
126*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd)                                  \
127*7c3d14c8STreehugger Robot   do {                                                                         \
128*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
129*7c3d14c8STreehugger Robot     (void)(fd);                                                                \
130*7c3d14c8STreehugger Robot   } while (false)
131*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd)                    \
132*7c3d14c8STreehugger Robot   do {                                                                         \
133*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
134*7c3d14c8STreehugger Robot     (void)(fd);                                                                \
135*7c3d14c8STreehugger Robot     (void)(newfd);                                                             \
136*7c3d14c8STreehugger Robot   } while (false)
137*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name)                          \
138*7c3d14c8STreehugger Robot   do {                                                                         \
139*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
140*7c3d14c8STreehugger Robot     (void)(name);                                                              \
141*7c3d14c8STreehugger Robot   } while (false)
142*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name)                 \
143*7c3d14c8STreehugger Robot   do {                                                                         \
144*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
145*7c3d14c8STreehugger Robot     (void)(thread);                                                            \
146*7c3d14c8STreehugger Robot     (void)(name);                                                              \
147*7c3d14c8STreehugger Robot   } while (false)
148*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
149*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m)                                  \
150*7c3d14c8STreehugger Robot   do {                                                                         \
151*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
152*7c3d14c8STreehugger Robot     (void)(m);                                                                 \
153*7c3d14c8STreehugger Robot   } while (false)
154*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m)                                \
155*7c3d14c8STreehugger Robot   do {                                                                         \
156*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
157*7c3d14c8STreehugger Robot     (void)(m);                                                                 \
158*7c3d14c8STreehugger Robot   } while (false)
159*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m)                                \
160*7c3d14c8STreehugger Robot   do {                                                                         \
161*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
162*7c3d14c8STreehugger Robot     (void)(m);                                                                 \
163*7c3d14c8STreehugger Robot   } while (false)
164*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg)                            \
165*7c3d14c8STreehugger Robot   do {                                                                         \
166*7c3d14c8STreehugger Robot     (void)(ctx);                                                               \
167*7c3d14c8STreehugger Robot     (void)(msg);                                                               \
168*7c3d14c8STreehugger Robot   } while (false)
169*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_USER_CALLBACK_START()                               \
170*7c3d14c8STreehugger Robot   do {                                                                         \
171*7c3d14c8STreehugger Robot   } while (false)
172*7c3d14c8STreehugger Robot #define COMMON_INTERCEPTOR_USER_CALLBACK_END()                                 \
173*7c3d14c8STreehugger Robot   do {                                                                         \
174*7c3d14c8STreehugger Robot   } while (false)
175*7c3d14c8STreehugger Robot 
176*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_common_interceptors.inc"
177*7c3d14c8STreehugger Robot 
178*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
179*7c3d14c8STreehugger Robot // Syscall interception
180*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
181*7c3d14c8STreehugger Robot 
182*7c3d14c8STreehugger Robot // We want the caller's PC b/c unlike the other function interceptors these
183*7c3d14c8STreehugger Robot // are separate pre and post functions called around the app's syscall().
184*7c3d14c8STreehugger Robot 
185*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_PRE_READ_RANGE(ptr, size)                               \
186*7c3d14c8STreehugger Robot   processRangeAccess(GET_CALLER_PC(), (uptr)ptr, size, false)
187*7c3d14c8STreehugger Robot 
188*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_PRE_WRITE_RANGE(ptr, size)                              \
189*7c3d14c8STreehugger Robot   do {                                                                         \
190*7c3d14c8STreehugger Robot     (void)(ptr);                                                               \
191*7c3d14c8STreehugger Robot     (void)(size);                                                              \
192*7c3d14c8STreehugger Robot   } while (false)
193*7c3d14c8STreehugger Robot 
194*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_POST_READ_RANGE(ptr, size)                              \
195*7c3d14c8STreehugger Robot   do {                                                                         \
196*7c3d14c8STreehugger Robot     (void)(ptr);                                                               \
197*7c3d14c8STreehugger Robot     (void)(size);                                                              \
198*7c3d14c8STreehugger Robot   } while (false)
199*7c3d14c8STreehugger Robot 
200*7c3d14c8STreehugger Robot // The actual amount written is in post, not pre.
201*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_POST_WRITE_RANGE(ptr, size)                             \
202*7c3d14c8STreehugger Robot   processRangeAccess(GET_CALLER_PC(), (uptr)ptr, size, true)
203*7c3d14c8STreehugger Robot 
204*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_ACQUIRE(addr)                                           \
205*7c3d14c8STreehugger Robot   do {                                                                         \
206*7c3d14c8STreehugger Robot     (void)(addr);                                                              \
207*7c3d14c8STreehugger Robot   } while (false)
208*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_RELEASE(addr)                                           \
209*7c3d14c8STreehugger Robot   do {                                                                         \
210*7c3d14c8STreehugger Robot     (void)(addr);                                                              \
211*7c3d14c8STreehugger Robot   } while (false)
212*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_FD_CLOSE(fd)                                            \
213*7c3d14c8STreehugger Robot   do {                                                                         \
214*7c3d14c8STreehugger Robot     (void)(fd);                                                                \
215*7c3d14c8STreehugger Robot   } while (false)
216*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_FD_ACQUIRE(fd)                                          \
217*7c3d14c8STreehugger Robot   do {                                                                         \
218*7c3d14c8STreehugger Robot     (void)(fd);                                                                \
219*7c3d14c8STreehugger Robot   } while (false)
220*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_FD_RELEASE(fd)                                          \
221*7c3d14c8STreehugger Robot   do {                                                                         \
222*7c3d14c8STreehugger Robot     (void)(fd);                                                                \
223*7c3d14c8STreehugger Robot   } while (false)
224*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_PRE_FORK()                                              \
225*7c3d14c8STreehugger Robot   do {                                                                         \
226*7c3d14c8STreehugger Robot   } while (false)
227*7c3d14c8STreehugger Robot #define COMMON_SYSCALL_POST_FORK(res)                                          \
228*7c3d14c8STreehugger Robot   do {                                                                         \
229*7c3d14c8STreehugger Robot     (void)(res);                                                               \
230*7c3d14c8STreehugger Robot   } while (false)
231*7c3d14c8STreehugger Robot 
232*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_common_syscalls.inc"
233*7c3d14c8STreehugger Robot 
234*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
235*7c3d14c8STreehugger Robot // Custom interceptors
236*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
237*7c3d14c8STreehugger Robot 
238*7c3d14c8STreehugger Robot // TODO(bruening): move more of these to the common interception pool as they
239*7c3d14c8STreehugger Robot // are shared with tsan and asan.
240*7c3d14c8STreehugger Robot // While our other files match LLVM style, here we match sanitizer style as we
241*7c3d14c8STreehugger Robot // expect to move these to the common pool.
242*7c3d14c8STreehugger Robot 
INTERCEPTOR(char *,strcpy,char * dst,const char * src)243*7c3d14c8STreehugger Robot INTERCEPTOR(char *, strcpy, char *dst, const char *src) { // NOLINT
244*7c3d14c8STreehugger Robot   void *ctx;
245*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, strcpy, dst, src);
246*7c3d14c8STreehugger Robot   uptr srclen = internal_strlen(src);
247*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, srclen + 1);
248*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_READ_RANGE(ctx, src, srclen + 1);
249*7c3d14c8STreehugger Robot   return REAL(strcpy)(dst, src); // NOLINT
250*7c3d14c8STreehugger Robot }
251*7c3d14c8STreehugger Robot 
INTERCEPTOR(char *,strncpy,char * dst,char * src,uptr n)252*7c3d14c8STreehugger Robot INTERCEPTOR(char *, strncpy, char *dst, char *src, uptr n) {
253*7c3d14c8STreehugger Robot   void *ctx;
254*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, strncpy, dst, src, n);
255*7c3d14c8STreehugger Robot   uptr srclen = internal_strnlen(src, n);
256*7c3d14c8STreehugger Robot   uptr copied_size = srclen + 1 > n ? n : srclen + 1;
257*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, copied_size);
258*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_READ_RANGE(ctx, src, copied_size);
259*7c3d14c8STreehugger Robot   return REAL(strncpy)(dst, src, n);
260*7c3d14c8STreehugger Robot }
261*7c3d14c8STreehugger Robot 
INTERCEPTOR(int,open,const char * name,int flags,int mode)262*7c3d14c8STreehugger Robot INTERCEPTOR(int, open, const char *name, int flags, int mode) {
263*7c3d14c8STreehugger Robot   void *ctx;
264*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, open, name, flags, mode);
265*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
266*7c3d14c8STreehugger Robot   return REAL(open)(name, flags, mode);
267*7c3d14c8STreehugger Robot }
268*7c3d14c8STreehugger Robot 
269*7c3d14c8STreehugger Robot #if SANITIZER_LINUX
INTERCEPTOR(int,open64,const char * name,int flags,int mode)270*7c3d14c8STreehugger Robot INTERCEPTOR(int, open64, const char *name, int flags, int mode) {
271*7c3d14c8STreehugger Robot   void *ctx;
272*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, open64, name, flags, mode);
273*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
274*7c3d14c8STreehugger Robot   return REAL(open64)(name, flags, mode);
275*7c3d14c8STreehugger Robot }
276*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_OPEN64 INTERCEPT_FUNCTION(open64)
277*7c3d14c8STreehugger Robot #else
278*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_OPEN64
279*7c3d14c8STreehugger Robot #endif
280*7c3d14c8STreehugger Robot 
INTERCEPTOR(int,creat,const char * name,int mode)281*7c3d14c8STreehugger Robot INTERCEPTOR(int, creat, const char *name, int mode) {
282*7c3d14c8STreehugger Robot   void *ctx;
283*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, creat, name, mode);
284*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
285*7c3d14c8STreehugger Robot   return REAL(creat)(name, mode);
286*7c3d14c8STreehugger Robot }
287*7c3d14c8STreehugger Robot 
288*7c3d14c8STreehugger Robot #if SANITIZER_LINUX
INTERCEPTOR(int,creat64,const char * name,int mode)289*7c3d14c8STreehugger Robot INTERCEPTOR(int, creat64, const char *name, int mode) {
290*7c3d14c8STreehugger Robot   void *ctx;
291*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, creat64, name, mode);
292*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
293*7c3d14c8STreehugger Robot   return REAL(creat64)(name, mode);
294*7c3d14c8STreehugger Robot }
295*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_CREAT64 INTERCEPT_FUNCTION(creat64)
296*7c3d14c8STreehugger Robot #else
297*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_CREAT64
298*7c3d14c8STreehugger Robot #endif
299*7c3d14c8STreehugger Robot 
INTERCEPTOR(int,unlink,char * path)300*7c3d14c8STreehugger Robot INTERCEPTOR(int, unlink, char *path) {
301*7c3d14c8STreehugger Robot   void *ctx;
302*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, unlink, path);
303*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
304*7c3d14c8STreehugger Robot   return REAL(unlink)(path);
305*7c3d14c8STreehugger Robot }
306*7c3d14c8STreehugger Robot 
INTERCEPTOR(uptr,fread,void * ptr,uptr size,uptr nmemb,void * f)307*7c3d14c8STreehugger Robot INTERCEPTOR(uptr, fread, void *ptr, uptr size, uptr nmemb, void *f) {
308*7c3d14c8STreehugger Robot   void *ctx;
309*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, f);
310*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size * nmemb);
311*7c3d14c8STreehugger Robot   return REAL(fread)(ptr, size, nmemb, f);
312*7c3d14c8STreehugger Robot }
313*7c3d14c8STreehugger Robot 
INTERCEPTOR(uptr,fwrite,const void * p,uptr size,uptr nmemb,void * f)314*7c3d14c8STreehugger Robot INTERCEPTOR(uptr, fwrite, const void *p, uptr size, uptr nmemb, void *f) {
315*7c3d14c8STreehugger Robot   void *ctx;
316*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, f);
317*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_READ_RANGE(ctx, p, size * nmemb);
318*7c3d14c8STreehugger Robot   return REAL(fwrite)(p, size, nmemb, f);
319*7c3d14c8STreehugger Robot }
320*7c3d14c8STreehugger Robot 
INTERCEPTOR(int,puts,const char * s)321*7c3d14c8STreehugger Robot INTERCEPTOR(int, puts, const char *s) {
322*7c3d14c8STreehugger Robot   void *ctx;
323*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, puts, s);
324*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_READ_RANGE(ctx, s, internal_strlen(s));
325*7c3d14c8STreehugger Robot   return REAL(puts)(s);
326*7c3d14c8STreehugger Robot }
327*7c3d14c8STreehugger Robot 
INTERCEPTOR(int,rmdir,char * path)328*7c3d14c8STreehugger Robot INTERCEPTOR(int, rmdir, char *path) {
329*7c3d14c8STreehugger Robot   void *ctx;
330*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, rmdir, path);
331*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
332*7c3d14c8STreehugger Robot   return REAL(rmdir)(path);
333*7c3d14c8STreehugger Robot }
334*7c3d14c8STreehugger Robot 
335*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
336*7c3d14c8STreehugger Robot // Shadow-related interceptors
337*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
338*7c3d14c8STreehugger Robot 
339*7c3d14c8STreehugger Robot // These are candidates for sharing with all sanitizers if shadow memory
340*7c3d14c8STreehugger Robot // support is also standardized.
341*7c3d14c8STreehugger Robot 
INTERCEPTOR(void *,mmap,void * addr,SIZE_T sz,int prot,int flags,int fd,OFF_T off)342*7c3d14c8STreehugger Robot INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags,
343*7c3d14c8STreehugger Robot                  int fd, OFF_T off) {
344*7c3d14c8STreehugger Robot   if (UNLIKELY(REAL(mmap) == nullptr)) {
345*7c3d14c8STreehugger Robot     // With esan init during interceptor init and a static libc preventing
346*7c3d14c8STreehugger Robot     // our early-calloc from triggering, we can end up here before our
347*7c3d14c8STreehugger Robot     // REAL pointer is set up.
348*7c3d14c8STreehugger Robot     return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
349*7c3d14c8STreehugger Robot   }
350*7c3d14c8STreehugger Robot   void *ctx;
351*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, mmap, addr, sz, prot, flags, fd, off);
352*7c3d14c8STreehugger Robot   if (!fixMmapAddr(&addr, sz, flags))
353*7c3d14c8STreehugger Robot     return (void *)-1;
354*7c3d14c8STreehugger Robot   void *result = REAL(mmap)(addr, sz, prot, flags, fd, off);
355*7c3d14c8STreehugger Robot   return (void *)checkMmapResult((uptr)result, sz);
356*7c3d14c8STreehugger Robot }
357*7c3d14c8STreehugger Robot 
358*7c3d14c8STreehugger Robot #if SANITIZER_LINUX
INTERCEPTOR(void *,mmap64,void * addr,SIZE_T sz,int prot,int flags,int fd,OFF64_T off)359*7c3d14c8STreehugger Robot INTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags,
360*7c3d14c8STreehugger Robot                  int fd, OFF64_T off) {
361*7c3d14c8STreehugger Robot   void *ctx;
362*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, mmap64, addr, sz, prot, flags, fd, off);
363*7c3d14c8STreehugger Robot   if (!fixMmapAddr(&addr, sz, flags))
364*7c3d14c8STreehugger Robot     return (void *)-1;
365*7c3d14c8STreehugger Robot   void *result = REAL(mmap64)(addr, sz, prot, flags, fd, off);
366*7c3d14c8STreehugger Robot   return (void *)checkMmapResult((uptr)result, sz);
367*7c3d14c8STreehugger Robot }
368*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_MMAP64 INTERCEPT_FUNCTION(mmap64)
369*7c3d14c8STreehugger Robot #else
370*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_MMAP64
371*7c3d14c8STreehugger Robot #endif
372*7c3d14c8STreehugger Robot 
373*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
374*7c3d14c8STreehugger Robot // Signal-related interceptors
375*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
376*7c3d14c8STreehugger Robot 
377*7c3d14c8STreehugger Robot #if SANITIZER_LINUX
378*7c3d14c8STreehugger Robot typedef void (*signal_handler_t)(int);
INTERCEPTOR(signal_handler_t,signal,int signum,signal_handler_t handler)379*7c3d14c8STreehugger Robot INTERCEPTOR(signal_handler_t, signal, int signum, signal_handler_t handler) {
380*7c3d14c8STreehugger Robot   void *ctx;
381*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, signal, signum, handler);
382*7c3d14c8STreehugger Robot   signal_handler_t result;
383*7c3d14c8STreehugger Robot   if (!processSignal(signum, handler, &result))
384*7c3d14c8STreehugger Robot     return result;
385*7c3d14c8STreehugger Robot   else
386*7c3d14c8STreehugger Robot     return REAL(signal)(signum, handler);
387*7c3d14c8STreehugger Robot }
388*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_SIGNAL INTERCEPT_FUNCTION(signal)
389*7c3d14c8STreehugger Robot #else
390*7c3d14c8STreehugger Robot #error Platform not supported
391*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_SIGNAL
392*7c3d14c8STreehugger Robot #endif
393*7c3d14c8STreehugger Robot 
394*7c3d14c8STreehugger Robot #if SANITIZER_LINUX
DECLARE_REAL(int,sigaction,int signum,const struct sigaction * act,struct sigaction * oldact)395*7c3d14c8STreehugger Robot DECLARE_REAL(int, sigaction, int signum, const struct sigaction *act,
396*7c3d14c8STreehugger Robot              struct sigaction *oldact)
397*7c3d14c8STreehugger Robot INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
398*7c3d14c8STreehugger Robot             struct sigaction *oldact) {
399*7c3d14c8STreehugger Robot   void *ctx;
400*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, sigaction, signum, act, oldact);
401*7c3d14c8STreehugger Robot   if (!processSigaction(signum, act, oldact))
402*7c3d14c8STreehugger Robot     return 0;
403*7c3d14c8STreehugger Robot   else
404*7c3d14c8STreehugger Robot     return REAL(sigaction)(signum, act, oldact);
405*7c3d14c8STreehugger Robot }
406*7c3d14c8STreehugger Robot 
407*7c3d14c8STreehugger Robot // This is required to properly use internal_sigaction.
408*7c3d14c8STreehugger Robot namespace __sanitizer {
real_sigaction(int signum,const void * act,void * oldact)409*7c3d14c8STreehugger Robot int real_sigaction(int signum, const void *act, void *oldact) {
410*7c3d14c8STreehugger Robot   if (REAL(sigaction) == nullptr) {
411*7c3d14c8STreehugger Robot     // With an instrumented allocator, this is called during interceptor init
412*7c3d14c8STreehugger Robot     // and we need a raw syscall solution.
413*7c3d14c8STreehugger Robot     return internal_sigaction_syscall(signum, act, oldact);
414*7c3d14c8STreehugger Robot   }
415*7c3d14c8STreehugger Robot   return REAL(sigaction)(signum, (const struct sigaction *)act,
416*7c3d14c8STreehugger Robot                          (struct sigaction *)oldact);
417*7c3d14c8STreehugger Robot }
418*7c3d14c8STreehugger Robot } // namespace __sanitizer
419*7c3d14c8STreehugger Robot 
420*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_SIGACTION INTERCEPT_FUNCTION(sigaction)
421*7c3d14c8STreehugger Robot #else
422*7c3d14c8STreehugger Robot #error Platform not supported
423*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_SIGACTION
424*7c3d14c8STreehugger Robot #endif
425*7c3d14c8STreehugger Robot 
426*7c3d14c8STreehugger Robot #if SANITIZER_LINUX
INTERCEPTOR(int,sigprocmask,int how,__sanitizer_sigset_t * set,__sanitizer_sigset_t * oldset)427*7c3d14c8STreehugger Robot INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
428*7c3d14c8STreehugger Robot             __sanitizer_sigset_t *oldset) {
429*7c3d14c8STreehugger Robot   void *ctx;
430*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
431*7c3d14c8STreehugger Robot   int res = 0;
432*7c3d14c8STreehugger Robot   if (processSigprocmask(how, set, oldset))
433*7c3d14c8STreehugger Robot     res = REAL(sigprocmask)(how, set, oldset);
434*7c3d14c8STreehugger Robot   if (!res && oldset)
435*7c3d14c8STreehugger Robot     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
436*7c3d14c8STreehugger Robot   return res;
437*7c3d14c8STreehugger Robot }
438*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_SIGPROCMASK INTERCEPT_FUNCTION(sigprocmask)
439*7c3d14c8STreehugger Robot #else
440*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_SIGPROCMASK
441*7c3d14c8STreehugger Robot #endif
442*7c3d14c8STreehugger Robot 
443*7c3d14c8STreehugger Robot #if !SANITIZER_WINDOWS
INTERCEPTOR(int,pthread_sigmask,int how,__sanitizer_sigset_t * set,__sanitizer_sigset_t * oldset)444*7c3d14c8STreehugger Robot INTERCEPTOR(int, pthread_sigmask, int how, __sanitizer_sigset_t *set,
445*7c3d14c8STreehugger Robot             __sanitizer_sigset_t *oldset) {
446*7c3d14c8STreehugger Robot   void *ctx;
447*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, pthread_sigmask, how, set, oldset);
448*7c3d14c8STreehugger Robot   int res = 0;
449*7c3d14c8STreehugger Robot   if (processSigprocmask(how, set, oldset))
450*7c3d14c8STreehugger Robot     res = REAL(sigprocmask)(how, set, oldset);
451*7c3d14c8STreehugger Robot   if (!res && oldset)
452*7c3d14c8STreehugger Robot     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
453*7c3d14c8STreehugger Robot   return res;
454*7c3d14c8STreehugger Robot }
455*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_PTHREAD_SIGMASK INTERCEPT_FUNCTION(pthread_sigmask)
456*7c3d14c8STreehugger Robot #else
457*7c3d14c8STreehugger Robot #define ESAN_MAYBE_INTERCEPT_PTHREAD_SIGMASK
458*7c3d14c8STreehugger Robot #endif
459*7c3d14c8STreehugger Robot 
460*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
461*7c3d14c8STreehugger Robot // Malloc interceptors
462*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
463*7c3d14c8STreehugger Robot 
464*7c3d14c8STreehugger Robot static char early_alloc_buf[128];
465*7c3d14c8STreehugger Robot static bool used_early_alloc_buf;
466*7c3d14c8STreehugger Robot 
handleEarlyAlloc(uptr size)467*7c3d14c8STreehugger Robot static void *handleEarlyAlloc(uptr size) {
468*7c3d14c8STreehugger Robot   // If esan is initialized during an interceptor (which happens with some
469*7c3d14c8STreehugger Robot   // tcmalloc implementations that call pthread_mutex_lock), the call from
470*7c3d14c8STreehugger Robot   // dlsym to calloc will deadlock.  There is only one such calloc (dlsym
471*7c3d14c8STreehugger Robot   // allocates a single pthread key), so we work around it by using a
472*7c3d14c8STreehugger Robot   // static buffer for the calloc request.  The loader currently needs
473*7c3d14c8STreehugger Robot   // 32 bytes but we size at 128 to allow for future changes.
474*7c3d14c8STreehugger Robot   // This solution will also allow us to deliberately intercept malloc & family
475*7c3d14c8STreehugger Robot   // in the future (to perform tool actions on each allocation, without
476*7c3d14c8STreehugger Robot   // replacing the allocator), as it also solves the problem of intercepting
477*7c3d14c8STreehugger Robot   // calloc when it will itself be called before its REAL pointer is
478*7c3d14c8STreehugger Robot   // initialized.
479*7c3d14c8STreehugger Robot   CHECK(!used_early_alloc_buf && size < sizeof(early_alloc_buf));
480*7c3d14c8STreehugger Robot   // We do not handle multiple threads here.  This only happens at process init
481*7c3d14c8STreehugger Robot   // time, and while it's possible for a shared library to create early threads
482*7c3d14c8STreehugger Robot   // that race here, we consider that to be a corner case extreme enough that
483*7c3d14c8STreehugger Robot   // it's not worth the effort to handle.
484*7c3d14c8STreehugger Robot   used_early_alloc_buf = true;
485*7c3d14c8STreehugger Robot   return (void *)early_alloc_buf;
486*7c3d14c8STreehugger Robot }
487*7c3d14c8STreehugger Robot 
INTERCEPTOR(void *,calloc,uptr size,uptr n)488*7c3d14c8STreehugger Robot INTERCEPTOR(void*, calloc, uptr size, uptr n) {
489*7c3d14c8STreehugger Robot   if (EsanDuringInit && REAL(calloc) == nullptr)
490*7c3d14c8STreehugger Robot     return handleEarlyAlloc(size * n);
491*7c3d14c8STreehugger Robot   void *ctx;
492*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, calloc, size, n);
493*7c3d14c8STreehugger Robot   void *res = REAL(calloc)(size, n);
494*7c3d14c8STreehugger Robot   // The memory is zeroed and thus is all written.
495*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_WRITE_RANGE(nullptr, (uptr)res, size * n);
496*7c3d14c8STreehugger Robot   return res;
497*7c3d14c8STreehugger Robot }
498*7c3d14c8STreehugger Robot 
INTERCEPTOR(void,free,void * p)499*7c3d14c8STreehugger Robot INTERCEPTOR(void, free, void *p) {
500*7c3d14c8STreehugger Robot   void *ctx;
501*7c3d14c8STreehugger Robot   COMMON_INTERCEPTOR_ENTER(ctx, free, p);
502*7c3d14c8STreehugger Robot   if (p == (void *)early_alloc_buf) {
503*7c3d14c8STreehugger Robot     // We expect just a singleton use but we clear this for cleanliness.
504*7c3d14c8STreehugger Robot     used_early_alloc_buf = false;
505*7c3d14c8STreehugger Robot     return;
506*7c3d14c8STreehugger Robot   }
507*7c3d14c8STreehugger Robot   REAL(free)(p);
508*7c3d14c8STreehugger Robot }
509*7c3d14c8STreehugger Robot 
510*7c3d14c8STreehugger Robot namespace __esan {
511*7c3d14c8STreehugger Robot 
initializeInterceptors()512*7c3d14c8STreehugger Robot void initializeInterceptors() {
513*7c3d14c8STreehugger Robot   InitializeCommonInterceptors();
514*7c3d14c8STreehugger Robot 
515*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION(strcpy); // NOLINT
516*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION(strncpy);
517*7c3d14c8STreehugger Robot 
518*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION(open);
519*7c3d14c8STreehugger Robot   ESAN_MAYBE_INTERCEPT_OPEN64;
520*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION(creat);
521*7c3d14c8STreehugger Robot   ESAN_MAYBE_INTERCEPT_CREAT64;
522*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION(unlink);
523*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION(fread);
524*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION(fwrite);
525*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION(puts);
526*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION(rmdir);
527*7c3d14c8STreehugger Robot 
528*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION(mmap);
529*7c3d14c8STreehugger Robot   ESAN_MAYBE_INTERCEPT_MMAP64;
530*7c3d14c8STreehugger Robot 
531*7c3d14c8STreehugger Robot   ESAN_MAYBE_INTERCEPT_SIGNAL;
532*7c3d14c8STreehugger Robot   ESAN_MAYBE_INTERCEPT_SIGACTION;
533*7c3d14c8STreehugger Robot   ESAN_MAYBE_INTERCEPT_SIGPROCMASK;
534*7c3d14c8STreehugger Robot   ESAN_MAYBE_INTERCEPT_PTHREAD_SIGMASK;
535*7c3d14c8STreehugger Robot 
536*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION(calloc);
537*7c3d14c8STreehugger Robot   INTERCEPT_FUNCTION(free);
538*7c3d14c8STreehugger Robot 
539*7c3d14c8STreehugger Robot   // TODO(bruening): intercept routines that other sanitizers intercept that
540*7c3d14c8STreehugger Robot   // are not in the common pool or here yet, ideally by adding to the common
541*7c3d14c8STreehugger Robot   // pool.  Examples include wcslen and bcopy.
542*7c3d14c8STreehugger Robot 
543*7c3d14c8STreehugger Robot   // TODO(bruening): there are many more libc routines that read or write data
544*7c3d14c8STreehugger Robot   // structures that no sanitizer is intercepting: sigaction, strtol, etc.
545*7c3d14c8STreehugger Robot }
546*7c3d14c8STreehugger Robot 
547*7c3d14c8STreehugger Robot } // namespace __esan
548