1//===--- rtsan_interceptors.cpp - Realtime Sanitizer ------------*- 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//===----------------------------------------------------------------------===//
10
11#include "sanitizer_common/sanitizer_platform.h"
12#if SANITIZER_POSIX
13
14#include "rtsan/rtsan_interceptors.h"
15
16#include "interception/interception.h"
17#include "sanitizer_common/sanitizer_allocator_dlsym.h"
18#include "sanitizer_common/sanitizer_glibc_version.h"
19#include "sanitizer_common/sanitizer_platform_interceptors.h"
20
21#include "interception/interception.h"
22#include "rtsan/rtsan.h"
23
24#if SANITIZER_APPLE
25#include <libkern/OSAtomic.h>
26#include <os/lock.h>
27#endif // SANITIZER_APPLE
28
29#if SANITIZER_INTERCEPT_MEMALIGN || SANITIZER_INTERCEPT_PVALLOC
30#include <malloc.h>
31#endif
32
33#include <fcntl.h>
34#include <poll.h>
35#include <pthread.h>
36#include <stdarg.h>
37#include <stdio.h>
38#if SANITIZER_LINUX
39#include <linux/mman.h>
40#include <sys/inotify.h>
41#endif
42#include <sys/select.h>
43#include <sys/socket.h>
44#include <sys/stat.h>
45#include <time.h>
46#include <unistd.h>
47
48using namespace __sanitizer;
49
50namespace {
51struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
52 static bool UseImpl() { return !__rtsan_is_initialized(); }
53};
54} // namespace
55
56// Filesystem
57
58INTERCEPTOR(int, open, const char *path, int oflag, ...) {
59 // We do not early exit if O_NONBLOCK is set.
60 // O_NONBLOCK **does not prevent the syscall** it simply sets the FD to be in
61 // nonblocking mode, which is a different concept than our
62 // [[clang::nonblocking]], and is not rt-safe. This behavior was confirmed
63 // using Instruments on Darwin with a simple test program
64 __rtsan_notify_intercepted_call(intercepted_function_name: "open");
65
66 if (OpenReadsVaArgs(oflag)) {
67 va_list args;
68 va_start(args, oflag);
69 const mode_t mode = va_arg(args, int);
70 va_end(args);
71 return REAL(open)(path, oflag, mode);
72 }
73
74 return REAL(open)(path, oflag);
75}
76
77#if SANITIZER_INTERCEPT_OPEN64
78INTERCEPTOR(int, open64, const char *path, int oflag, ...) {
79 // See comment above about O_NONBLOCK
80 __rtsan_notify_intercepted_call(intercepted_function_name: "open64");
81
82 if (OpenReadsVaArgs(oflag)) {
83 va_list args;
84 va_start(args, oflag);
85 const mode_t mode = va_arg(args, int);
86 va_end(args);
87 return REAL(open64)(path, oflag, mode);
88 }
89
90 return REAL(open64)(path, oflag);
91}
92#define RTSAN_MAYBE_INTERCEPT_OPEN64 INTERCEPT_FUNCTION(open64)
93#else
94#define RTSAN_MAYBE_INTERCEPT_OPEN64
95#endif // SANITIZER_INTERCEPT_OPEN64
96
97INTERCEPTOR(int, openat, int fd, const char *path, int oflag, ...) {
98 // See comment above about O_NONBLOCK
99 __rtsan_notify_intercepted_call(intercepted_function_name: "openat");
100
101 if (OpenReadsVaArgs(oflag)) {
102 va_list args;
103 va_start(args, oflag);
104 const mode_t mode = va_arg(args, int);
105 va_end(args);
106 return REAL(openat)(fd, path, oflag, mode);
107 }
108
109 return REAL(openat)(fd, path, oflag);
110}
111
112#if SANITIZER_INTERCEPT_OPENAT64
113INTERCEPTOR(int, openat64, int fd, const char *path, int oflag, ...) {
114 // See comment above about O_NONBLOCK
115 __rtsan_notify_intercepted_call(intercepted_function_name: "openat64");
116
117 if (OpenReadsVaArgs(oflag)) {
118 va_list args;
119 va_start(args, oflag);
120 const mode_t mode = va_arg(args, int);
121 va_end(args);
122 return REAL(openat64)(fd, path, oflag, mode);
123 }
124
125 return REAL(openat64)(fd, path, oflag);
126}
127#define RTSAN_MAYBE_INTERCEPT_OPENAT64 INTERCEPT_FUNCTION(openat64)
128#else
129#define RTSAN_MAYBE_INTERCEPT_OPENAT64
130#endif // SANITIZER_INTERCEPT_OPENAT64
131
132INTERCEPTOR(int, creat, const char *path, mode_t mode) {
133 // See comment above about O_NONBLOCK
134 __rtsan_notify_intercepted_call(intercepted_function_name: "creat");
135 const int result = REAL(creat)(path, mode);
136 return result;
137}
138
139#if SANITIZER_INTERCEPT_CREAT64
140INTERCEPTOR(int, creat64, const char *path, mode_t mode) {
141 // See comment above about O_NONBLOCK
142 __rtsan_notify_intercepted_call(intercepted_function_name: "creat64");
143 const int result = REAL(creat64)(path, mode);
144 return result;
145}
146#define RTSAN_MAYBE_INTERCEPT_CREAT64 INTERCEPT_FUNCTION(creat64)
147#else
148#define RTSAN_MAYBE_INTERCEPT_CREAT64
149#endif // SANITIZER_INTERCEPT_CREAT64
150
151INTERCEPTOR(int, fcntl, int filedes, int cmd, ...) {
152 __rtsan_notify_intercepted_call(intercepted_function_name: "fcntl");
153
154 // Following precedent here. The linux source (fcntl.c, do_fcntl) accepts the
155 // final argument in a variable that will hold the largest of the possible
156 // argument types. It is then assumed that the implementation of fcntl will
157 // cast it properly depending on cmd.
158 //
159 // The two types we expect for possible args are `struct flock*` and `int`
160 // we will cast to `intptr_t` which should hold both comfortably.
161 // Why `intptr_t`? It should fit both types, and it follows the freeBSD
162 // approach linked below.
163 using arg_type = intptr_t;
164 static_assert(sizeof(arg_type) >= sizeof(struct flock *));
165 static_assert(sizeof(arg_type) >= sizeof(int));
166
167 // Some cmds will not actually have an argument passed in this va_list.
168 // Calling va_arg when no arg exists is UB, however all currently
169 // supported architectures will give us a result in all three cases
170 // (no arg/int arg/struct flock* arg)
171 // va_arg() will generally read the next argument register or the
172 // stack. If we ever support an arch like CHERI with bounds checking, we
173 // may have to re-evaluate this approach.
174 //
175 // More discussion, and other examples following this approach
176 // https://discourse.llvm.org/t/how-to-write-an-interceptor-for-fcntl/81203
177 // https://reviews.freebsd.org/D46403
178 // https://github.com/bminor/glibc/blob/c444cc1d8335243c5c4e636d6a26c472df85522c/sysdeps/unix/sysv/linux/fcntl64.c#L37-L46
179
180 va_list args;
181 va_start(args, cmd);
182 const arg_type arg = va_arg(args, arg_type);
183 va_end(args);
184
185 return REAL(fcntl)(filedes, cmd, arg);
186}
187
188#if SANITIZER_MUSL
189INTERCEPTOR(int, ioctl, int filedes, int request, ...) {
190#else
191INTERCEPTOR(int, ioctl, int filedes, unsigned long request, ...) {
192#endif
193 __rtsan_notify_intercepted_call(intercepted_function_name: "ioctl");
194
195 // See fcntl for discussion on why we use intptr_t
196 // And why we read from va_args on all request types
197 using arg_type = intptr_t;
198 static_assert(sizeof(arg_type) >= sizeof(struct ifreq *));
199 static_assert(sizeof(arg_type) >= sizeof(int));
200
201 va_list args;
202 va_start(args, request);
203 arg_type arg = va_arg(args, arg_type);
204 va_end(args);
205
206 return REAL(ioctl)(filedes, request, arg);
207}
208
209#if SANITIZER_INTERCEPT_FCNTL64
210INTERCEPTOR(int, fcntl64, int filedes, int cmd, ...) {
211 __rtsan_notify_intercepted_call(intercepted_function_name: "fcntl64");
212
213 va_list args;
214 va_start(args, cmd);
215
216 // Following precedent here. The linux source (fcntl.c, do_fcntl) accepts the
217 // final argument in a variable that will hold the largest of the possible
218 // argument types (pointers and ints are typical in fcntl) It is then assumed
219 // that the implementation of fcntl will cast it properly depending on cmd.
220 //
221 // This is also similar to what is done in
222 // sanitizer_common/sanitizer_common_syscalls.inc
223 const unsigned long arg = va_arg(args, unsigned long);
224 int result = REAL(fcntl64)(filedes, cmd, arg);
225
226 va_end(args);
227
228 return result;
229}
230#define RTSAN_MAYBE_INTERCEPT_FCNTL64 INTERCEPT_FUNCTION(fcntl64)
231#else
232#define RTSAN_MAYBE_INTERCEPT_FCNTL64
233#endif // SANITIZER_INTERCEPT_FCNTL64
234
235INTERCEPTOR(int, close, int filedes) {
236 __rtsan_notify_intercepted_call(intercepted_function_name: "close");
237 return REAL(close)(filedes);
238}
239
240INTERCEPTOR(int, chdir, const char *path) {
241 __rtsan_notify_intercepted_call(intercepted_function_name: "chdir");
242 return REAL(chdir)(path);
243}
244
245INTERCEPTOR(int, fchdir, int fd) {
246 __rtsan_notify_intercepted_call(intercepted_function_name: "fchdir");
247 return REAL(fchdir)(fd);
248}
249
250#if SANITIZER_INTERCEPT_READLINK
251INTERCEPTOR(ssize_t, readlink, const char *pathname, char *buf, size_t size) {
252 __rtsan_notify_intercepted_call(intercepted_function_name: "readlink");
253 return REAL(readlink)(pathname, buf, size);
254}
255#define RTSAN_MAYBE_INTERCEPT_READLINK INTERCEPT_FUNCTION(readlink)
256#else
257#define RTSAN_MAYBE_INTERCEPT_READLINK
258#endif
259
260#if SANITIZER_INTERCEPT_READLINKAT
261INTERCEPTOR(ssize_t, readlinkat, int dirfd, const char *pathname, char *buf,
262 size_t size) {
263 __rtsan_notify_intercepted_call(intercepted_function_name: "readlinkat");
264 return REAL(readlinkat)(dirfd, pathname, buf, size);
265}
266#define RTSAN_MAYBE_INTERCEPT_READLINKAT INTERCEPT_FUNCTION(readlinkat)
267#else
268#define RTSAN_MAYBE_INTERCEPT_READLINKAT
269#endif
270
271INTERCEPTOR(int, unlink, const char *pathname) {
272 __rtsan_notify_intercepted_call(intercepted_function_name: "unlink");
273 return REAL(unlink)(pathname);
274}
275
276INTERCEPTOR(int, unlinkat, int fd, const char *pathname, int flag) {
277 __rtsan_notify_intercepted_call(intercepted_function_name: "unlinkat");
278 return REAL(unlinkat)(fd, pathname, flag);
279}
280
281INTERCEPTOR(int, truncate, const char *pathname, off_t length) {
282 __rtsan_notify_intercepted_call(intercepted_function_name: "truncate");
283 return REAL(truncate)(pathname, length);
284}
285
286INTERCEPTOR(int, ftruncate, int fd, off_t length) {
287 __rtsan_notify_intercepted_call(intercepted_function_name: "ftruncate");
288 return REAL(ftruncate)(fd, length);
289}
290
291#if SANITIZER_LINUX && !SANITIZER_MUSL
292INTERCEPTOR(int, truncate64, const char *pathname, off64_t length) {
293 __rtsan_notify_intercepted_call(intercepted_function_name: "truncate64");
294 return REAL(truncate64)(pathname, length);
295}
296
297INTERCEPTOR(int, ftruncate64, int fd, off64_t length) {
298 __rtsan_notify_intercepted_call(intercepted_function_name: "ftruncate64");
299 return REAL(ftruncate64)(fd, length);
300}
301#define RTSAN_MAYBE_INTERCEPT_TRUNCATE64 INTERCEPT_FUNCTION(truncate64)
302#define RTSAN_MAYBE_INTERCEPT_FTRUNCATE64 INTERCEPT_FUNCTION(ftruncate64)
303#else
304#define RTSAN_MAYBE_INTERCEPT_TRUNCATE64
305#define RTSAN_MAYBE_INTERCEPT_FTRUNCATE64
306#endif
307
308INTERCEPTOR(int, symlink, const char *target, const char *linkpath) {
309 __rtsan_notify_intercepted_call(intercepted_function_name: "symlink");
310 return REAL(symlink)(target, linkpath);
311}
312
313INTERCEPTOR(int, symlinkat, const char *target, int newdirfd,
314 const char *linkpath) {
315 __rtsan_notify_intercepted_call(intercepted_function_name: "symlinkat");
316 return REAL(symlinkat)(target, newdirfd, linkpath);
317}
318
319// Streams
320
321INTERCEPTOR(FILE *, fopen, const char *path, const char *mode) {
322 __rtsan_notify_intercepted_call(intercepted_function_name: "fopen");
323 return REAL(fopen)(path, mode);
324}
325
326INTERCEPTOR(FILE *, freopen, const char *path, const char *mode, FILE *stream) {
327 __rtsan_notify_intercepted_call(intercepted_function_name: "freopen");
328 return REAL(freopen)(path, mode, stream);
329}
330
331#if SANITIZER_INTERCEPT_FOPEN64
332INTERCEPTOR(FILE *, fopen64, const char *path, const char *mode) {
333 __rtsan_notify_intercepted_call(intercepted_function_name: "fopen64");
334 return REAL(fopen64)(path, mode);
335}
336
337INTERCEPTOR(FILE *, freopen64, const char *path, const char *mode,
338 FILE *stream) {
339 __rtsan_notify_intercepted_call(intercepted_function_name: "freopen64");
340 return REAL(freopen64)(path, mode, stream);
341}
342#define RTSAN_MAYBE_INTERCEPT_FOPEN64 INTERCEPT_FUNCTION(fopen64);
343#define RTSAN_MAYBE_INTERCEPT_FREOPEN64 INTERCEPT_FUNCTION(freopen64);
344#else
345#define RTSAN_MAYBE_INTERCEPT_FOPEN64
346#define RTSAN_MAYBE_INTERCEPT_FREOPEN64
347#endif // SANITIZER_INTERCEPT_FOPEN64
348
349INTERCEPTOR(size_t, fread, void *ptr, size_t size, size_t nitems,
350 FILE *stream) {
351 __rtsan_notify_intercepted_call(intercepted_function_name: "fread");
352 return REAL(fread)(ptr, size, nitems, stream);
353}
354
355INTERCEPTOR(size_t, fwrite, const void *ptr, size_t size, size_t nitems,
356 FILE *stream) {
357 __rtsan_notify_intercepted_call(intercepted_function_name: "fwrite");
358 return REAL(fwrite)(ptr, size, nitems, stream);
359}
360
361INTERCEPTOR(int, fclose, FILE *stream) {
362 __rtsan_notify_intercepted_call(intercepted_function_name: "fclose");
363 return REAL(fclose)(stream);
364}
365
366INTERCEPTOR(int, fputs, const char *s, FILE *stream) {
367 __rtsan_notify_intercepted_call(intercepted_function_name: "fputs");
368 return REAL(fputs)(s, stream);
369}
370
371INTERCEPTOR(int, fflush, FILE *stream) {
372 __rtsan_notify_intercepted_call(intercepted_function_name: "fflush");
373 return REAL(fflush)(stream);
374}
375
376#if SANITIZER_APPLE
377INTERCEPTOR(int, fpurge, FILE *stream) {
378 __rtsan_notify_intercepted_call("fpurge");
379 return REAL(fpurge)(stream);
380}
381#define RTSAN_MAYBE_INTERCEPT_FPURGE INTERCEPT_FUNCTION(fpurge)
382#else
383#define RTSAN_MAYBE_INTERCEPT_FPURGE
384#endif
385
386INTERCEPTOR(FILE *, fdopen, int fd, const char *mode) {
387 __rtsan_notify_intercepted_call(intercepted_function_name: "fdopen");
388 return REAL(fdopen)(fd, mode);
389}
390
391#if SANITIZER_INTERCEPT_FOPENCOOKIE
392INTERCEPTOR(FILE *, fopencookie, void *cookie, const char *mode,
393 cookie_io_functions_t funcs) {
394 __rtsan_notify_intercepted_call(intercepted_function_name: "fopencookie");
395 return REAL(fopencookie)(cookie, mode, funcs);
396}
397#define RTSAN_MAYBE_INTERCEPT_FOPENCOOKIE INTERCEPT_FUNCTION(fopencookie)
398#else
399#define RTSAN_MAYBE_INTERCEPT_FOPENCOOKIE
400#endif
401
402#if SANITIZER_INTERCEPT_OPEN_MEMSTREAM
403INTERCEPTOR(FILE *, open_memstream, char **buf, size_t *size) {
404 __rtsan_notify_intercepted_call(intercepted_function_name: "open_memstream");
405 return REAL(open_memstream)(buf, size);
406}
407
408INTERCEPTOR(FILE *, fmemopen, void *buf, size_t size, const char *mode) {
409 __rtsan_notify_intercepted_call(intercepted_function_name: "fmemopen");
410 return REAL(fmemopen)(buf, size, mode);
411}
412#define RTSAN_MAYBE_INTERCEPT_OPEN_MEMSTREAM INTERCEPT_FUNCTION(open_memstream)
413#define RTSAN_MAYBE_INTERCEPT_FMEMOPEN INTERCEPT_FUNCTION(fmemopen)
414#else
415#define RTSAN_MAYBE_INTERCEPT_OPEN_MEMSTREAM
416#define RTSAN_MAYBE_INTERCEPT_FMEMOPEN
417#endif
418
419#if SANITIZER_INTERCEPT_SETVBUF
420INTERCEPTOR(void, setbuf, FILE *stream, char *buf) {
421 __rtsan_notify_intercepted_call(intercepted_function_name: "setbuf");
422 return REAL(setbuf)(stream, buf);
423}
424
425INTERCEPTOR(int, setvbuf, FILE *stream, char *buf, int mode, size_t size) {
426 __rtsan_notify_intercepted_call(intercepted_function_name: "setvbuf");
427 return REAL(setvbuf)(stream, buf, mode, size);
428}
429
430#if SANITIZER_LINUX
431INTERCEPTOR(void, setlinebuf, FILE *stream) {
432#else
433INTERCEPTOR(int, setlinebuf, FILE *stream) {
434#endif
435 __rtsan_notify_intercepted_call(intercepted_function_name: "setlinebuf");
436 return REAL(setlinebuf)(stream);
437}
438
439#if SANITIZER_LINUX
440INTERCEPTOR(void, setbuffer, FILE *stream, char *buf, size_t size) {
441#else
442INTERCEPTOR(void, setbuffer, FILE *stream, char *buf, int size) {
443#endif
444 __rtsan_notify_intercepted_call(intercepted_function_name: "setbuffer");
445 return REAL(setbuffer)(stream, buf, size);
446}
447#define RTSAN_MAYBE_INTERCEPT_SETBUF INTERCEPT_FUNCTION(setbuf)
448#define RTSAN_MAYBE_INTERCEPT_SETVBUF INTERCEPT_FUNCTION(setvbuf)
449#define RTSAN_MAYBE_INTERCEPT_SETLINEBUF INTERCEPT_FUNCTION(setlinebuf)
450#define RTSAN_MAYBE_INTERCEPT_SETBUFFER INTERCEPT_FUNCTION(setbuffer)
451#else
452#define RTSAN_MAYBE_INTERCEPT_SETBUF
453#define RTSAN_MAYBE_INTERCEPT_SETVBUF
454#define RTSAN_MAYBE_INTERCEPT_SETLINEBUF
455#define RTSAN_MAYBE_INTERCEPT_SETBUFFER
456#endif
457
458#if SANITIZER_INTERCEPT_FSEEK
459INTERCEPTOR(int, fgetpos, FILE *stream, fpos_t *pos) {
460 __rtsan_notify_intercepted_call(intercepted_function_name: "fgetpos");
461 return REAL(fgetpos)(stream, pos);
462}
463
464INTERCEPTOR(int, fseek, FILE *stream, long offset, int whence) {
465 __rtsan_notify_intercepted_call(intercepted_function_name: "fseek");
466 return REAL(fseek)(stream, offset, whence);
467}
468
469INTERCEPTOR(int, fseeko, FILE *stream, off_t offset, int whence) {
470 __rtsan_notify_intercepted_call(intercepted_function_name: "fseeko");
471 return REAL(fseeko)(stream, offset, whence);
472}
473
474INTERCEPTOR(int, fsetpos, FILE *stream, const fpos_t *pos) {
475 __rtsan_notify_intercepted_call(intercepted_function_name: "fsetpos");
476 return REAL(fsetpos)(stream, pos);
477}
478
479INTERCEPTOR(long, ftell, FILE *stream) {
480 __rtsan_notify_intercepted_call(intercepted_function_name: "ftell");
481 return REAL(ftell)(stream);
482}
483
484INTERCEPTOR(off_t, ftello, FILE *stream) {
485 __rtsan_notify_intercepted_call(intercepted_function_name: "ftello");
486 return REAL(ftello)(stream);
487}
488
489#if SANITIZER_LINUX && !SANITIZER_MUSL
490INTERCEPTOR(int, fgetpos64, FILE *stream, fpos64_t *pos) {
491 __rtsan_notify_intercepted_call(intercepted_function_name: "fgetpos64");
492 return REAL(fgetpos64)(stream, pos);
493}
494
495INTERCEPTOR(int, fseeko64, FILE *stream, off64_t offset, int whence) {
496 __rtsan_notify_intercepted_call(intercepted_function_name: "fseeko64");
497 return REAL(fseeko64)(stream, offset, whence);
498}
499
500INTERCEPTOR(int, fsetpos64, FILE *stream, const fpos64_t *pos) {
501 __rtsan_notify_intercepted_call(intercepted_function_name: "fsetpos64");
502 return REAL(fsetpos64)(stream, pos);
503}
504
505INTERCEPTOR(off64_t, ftello64, FILE *stream) {
506 __rtsan_notify_intercepted_call(intercepted_function_name: "ftello64");
507 return REAL(ftello64)(stream);
508}
509#endif
510
511INTERCEPTOR(void, rewind, FILE *stream) {
512 __rtsan_notify_intercepted_call(intercepted_function_name: "rewind");
513 return REAL(rewind)(stream);
514}
515#define RTSAN_MAYBE_INTERCEPT_FGETPOS INTERCEPT_FUNCTION(fgetpos)
516#define RTSAN_MAYBE_INTERCEPT_FSEEK INTERCEPT_FUNCTION(fseek)
517#define RTSAN_MAYBE_INTERCEPT_FSEEKO INTERCEPT_FUNCTION(fseeko)
518#define RTSAN_MAYBE_INTERCEPT_FSETPOS INTERCEPT_FUNCTION(fsetpos)
519#define RTSAN_MAYBE_INTERCEPT_FTELL INTERCEPT_FUNCTION(ftell)
520#define RTSAN_MAYBE_INTERCEPT_FTELLO INTERCEPT_FUNCTION(ftello)
521#define RTSAN_MAYBE_INTERCEPT_REWIND INTERCEPT_FUNCTION(rewind)
522#if SANITIZER_LINUX && !SANITIZER_MUSL
523#define RTSAN_MAYBE_INTERCEPT_FGETPOS64 INTERCEPT_FUNCTION(fgetpos64)
524#define RTSAN_MAYBE_INTERCEPT_FSEEKO64 INTERCEPT_FUNCTION(fseeko64)
525#define RTSAN_MAYBE_INTERCEPT_FSETPOS64 INTERCEPT_FUNCTION(fsetpos64)
526#define RTSAN_MAYBE_INTERCEPT_FTELLO64 INTERCEPT_FUNCTION(ftello64)
527#else
528#define RTSAN_MAYBE_INTERCEPT_FGETPOS64
529#define RTSAN_MAYBE_INTERCEPT_FSEEKO64
530#define RTSAN_MAYBE_INTERCEPT_FSETPOS64
531#define RTSAN_MAYBE_INTERCEPT_FTELLO64
532#endif
533#else
534#define RTSAN_MAYBE_INTERCEPT_FGETPOS
535#define RTSAN_MAYBE_INTERCEPT_FSEEK
536#define RTSAN_MAYBE_INTERCEPT_FSEEKO
537#define RTSAN_MAYBE_INTERCEPT_FSETPOS
538#define RTSAN_MAYBE_INTERCEPT_FTELL
539#define RTSAN_MAYBE_INTERCEPT_FTELLO
540#define RTSAN_MAYBE_INTERCEPT_REWIND
541#define RTSAN_MAYBE_INTERCEPT_FGETPOS64
542#define RTSAN_MAYBE_INTERCEPT_FSEEKO64
543#define RTSAN_MAYBE_INTERCEPT_FSETPOS64
544#define RTSAN_MAYBE_INTERCEPT_FTELLO64
545#endif
546
547INTERCEPTOR(int, puts, const char *s) {
548 __rtsan_notify_intercepted_call(intercepted_function_name: "puts");
549 return REAL(puts)(s);
550}
551
552INTERCEPTOR(ssize_t, read, int fd, void *buf, size_t count) {
553 __rtsan_notify_intercepted_call(intercepted_function_name: "read");
554 return REAL(read)(fd, buf, count);
555}
556
557INTERCEPTOR(ssize_t, write, int fd, const void *buf, size_t count) {
558 __rtsan_notify_intercepted_call(intercepted_function_name: "write");
559 return REAL(write)(fd, buf, count);
560}
561
562INTERCEPTOR(ssize_t, pread, int fd, void *buf, size_t count, off_t offset) {
563 __rtsan_notify_intercepted_call(intercepted_function_name: "pread");
564 return REAL(pread)(fd, buf, count, offset);
565}
566
567#if SANITIZER_INTERCEPT_PREAD64
568INTERCEPTOR(ssize_t, pread64, int fd, void *buf, size_t count, off_t offset) {
569 __rtsan_notify_intercepted_call(intercepted_function_name: "pread64");
570 return REAL(pread64)(fd, buf, count, offset);
571}
572#define RTSAN_MAYBE_INTERCEPT_PREAD64 INTERCEPT_FUNCTION(pread64)
573#else
574#define RTSAN_MAYBE_INTERCEPT_PREAD64
575#endif // SANITIZER_INTERCEPT_PREAD64
576
577INTERCEPTOR(ssize_t, readv, int fd, const struct iovec *iov, int iovcnt) {
578 __rtsan_notify_intercepted_call(intercepted_function_name: "readv");
579 return REAL(readv)(fd, iov, iovcnt);
580}
581
582INTERCEPTOR(ssize_t, pwrite, int fd, const void *buf, size_t count,
583 off_t offset) {
584 __rtsan_notify_intercepted_call(intercepted_function_name: "pwrite");
585 return REAL(pwrite)(fd, buf, count, offset);
586}
587
588#if SANITIZER_INTERCEPT_PWRITE64
589INTERCEPTOR(ssize_t, pwrite64, int fd, const void *buf, size_t count,
590 off_t offset) {
591 __rtsan_notify_intercepted_call(intercepted_function_name: "pwrite64");
592 return REAL(pwrite64)(fd, buf, count, offset);
593}
594#define RTSAN_MAYBE_INTERCEPT_PWRITE64 INTERCEPT_FUNCTION(pwrite64)
595#else
596#define RTSAN_MAYBE_INTERCEPT_PWRITE64
597#endif // SANITIZER_INTERCEPT_PWRITE64
598
599#if SANITIZER_INTERCEPT_PREADV
600INTERCEPTOR(ssize_t, preadv, int fd, const struct iovec *iov, int count,
601 off_t offset) {
602 __rtsan_notify_intercepted_call(intercepted_function_name: "preadv");
603 return REAL(preadv)(fd, iov, count, offset);
604}
605#define RTSAN_MAYBE_INTERCEPT_PREADV INTERCEPT_FUNCTION(preadv)
606#else
607#define RTSAN_MAYBE_INTERCEPT_PREADV
608#endif
609
610#if SANITIZER_INTERCEPT_PREADV64
611INTERCEPTOR(ssize_t, preadv64, int fd, const struct iovec *iov, int count,
612 off_t offset) {
613 __rtsan_notify_intercepted_call(intercepted_function_name: "preadv64");
614 return REAL(preadv64)(fd, iov, count, offset);
615}
616#define RTSAN_MAYBE_INTERCEPT_PREADV64 INTERCEPT_FUNCTION(preadv64)
617#else
618#define RTSAN_MAYBE_INTERCEPT_PREADV64
619#endif
620
621#if SANITIZER_INTERCEPT_PWRITEV
622INTERCEPTOR(ssize_t, pwritev, int fd, const struct iovec *iov, int count,
623 off_t offset) {
624 __rtsan_notify_intercepted_call(intercepted_function_name: "pwritev");
625 return REAL(pwritev)(fd, iov, count, offset);
626}
627#define RTSAN_MAYBE_INTERCEPT_PWRITEV INTERCEPT_FUNCTION(pwritev)
628#else
629#define RTSAN_MAYBE_INTERCEPT_PWRITEV
630#endif
631
632#if SANITIZER_INTERCEPT_PWRITEV64
633INTERCEPTOR(ssize_t, pwritev64, int fd, const struct iovec *iov, int count,
634 off_t offset) {
635 __rtsan_notify_intercepted_call(intercepted_function_name: "pwritev64");
636 return REAL(pwritev64)(fd, iov, count, offset);
637}
638#define RTSAN_MAYBE_INTERCEPT_PWRITEV64 INTERCEPT_FUNCTION(pwritev64)
639#else
640#define RTSAN_MAYBE_INTERCEPT_PWRITEV64
641#endif
642
643INTERCEPTOR(ssize_t, writev, int fd, const struct iovec *iov, int iovcnt) {
644 __rtsan_notify_intercepted_call(intercepted_function_name: "writev");
645 return REAL(writev)(fd, iov, iovcnt);
646}
647
648INTERCEPTOR(off_t, lseek, int fd, off_t offset, int whence) {
649 __rtsan_notify_intercepted_call(intercepted_function_name: "lseek");
650 return REAL(lseek)(fd, offset, whence);
651}
652
653#if SANITIZER_INTERCEPT_LSEEK64
654INTERCEPTOR(off64_t, lseek64, int fd, off64_t offset, int whence) {
655 __rtsan_notify_intercepted_call(intercepted_function_name: "lseek64");
656 return REAL(lseek64)(fd, offset, whence);
657}
658#define RTSAN_MAYBE_INTERCEPT_LSEEK64 INTERCEPT_FUNCTION(lseek64)
659#else
660#define RTSAN_MAYBE_INTERCEPT_LSEEK64
661#endif // SANITIZER_INTERCEPT_LSEEK64
662
663INTERCEPTOR(int, dup, int oldfd) {
664 __rtsan_notify_intercepted_call(intercepted_function_name: "dup");
665 return REAL(dup)(oldfd);
666}
667
668INTERCEPTOR(int, dup2, int oldfd, int newfd) {
669 __rtsan_notify_intercepted_call(intercepted_function_name: "dup2");
670 return REAL(dup2)(oldfd, newfd);
671}
672
673INTERCEPTOR(int, chmod, const char *path, mode_t mode) {
674 __rtsan_notify_intercepted_call(intercepted_function_name: "chmod");
675 return REAL(chmod)(path, mode);
676}
677
678INTERCEPTOR(int, fchmod, int fd, mode_t mode) {
679 __rtsan_notify_intercepted_call(intercepted_function_name: "fchmod");
680 return REAL(fchmod)(fd, mode);
681}
682
683INTERCEPTOR(int, mkdir, const char *path, mode_t mode) {
684 __rtsan_notify_intercepted_call(intercepted_function_name: "mkdir");
685 return REAL(mkdir)(path, mode);
686}
687
688INTERCEPTOR(int, rmdir, const char *path) {
689 __rtsan_notify_intercepted_call(intercepted_function_name: "rmdir");
690 return REAL(rmdir)(path);
691}
692
693INTERCEPTOR(mode_t, umask, mode_t cmask) {
694 __rtsan_notify_intercepted_call(intercepted_function_name: "umask");
695 return REAL(umask)(cmask);
696}
697
698// Concurrency
699#if SANITIZER_APPLE
700#pragma clang diagnostic push
701// OSSpinLockLock is deprecated, but still in use in libc++
702#pragma clang diagnostic ignored "-Wdeprecated-declarations"
703#undef OSSpinLockLock
704
705INTERCEPTOR(void, OSSpinLockLock, volatile OSSpinLock *lock) {
706 __rtsan_notify_intercepted_call("OSSpinLockLock");
707 return REAL(OSSpinLockLock)(lock);
708}
709
710#define RTSAN_MAYBE_INTERCEPT_OSSPINLOCKLOCK INTERCEPT_FUNCTION(OSSpinLockLock)
711#else
712#define RTSAN_MAYBE_INTERCEPT_OSSPINLOCKLOCK
713#endif // SANITIZER_APPLE
714
715#if SANITIZER_APPLE
716// _os_nospin_lock_lock may replace OSSpinLockLock due to deprecation macro.
717typedef volatile OSSpinLock *_os_nospin_lock_t;
718
719INTERCEPTOR(void, _os_nospin_lock_lock, _os_nospin_lock_t lock) {
720 __rtsan_notify_intercepted_call("_os_nospin_lock_lock");
721 return REAL(_os_nospin_lock_lock)(lock);
722}
723#pragma clang diagnostic pop // "-Wdeprecated-declarations"
724#endif // SANITIZER_APPLE
725
726#if SANITIZER_APPLE
727INTERCEPTOR(void, os_unfair_lock_lock, os_unfair_lock_t lock) {
728 __rtsan_notify_intercepted_call("os_unfair_lock_lock");
729 return REAL(os_unfair_lock_lock)(lock);
730}
731
732#define RTSAN_MAYBE_INTERCEPT_OS_UNFAIR_LOCK_LOCK \
733 INTERCEPT_FUNCTION(os_unfair_lock_lock)
734#else
735#define RTSAN_MAYBE_INTERCEPT_OS_UNFAIR_LOCK_LOCK
736#endif // SANITIZER_APPLE
737
738#if SANITIZER_LINUX
739INTERCEPTOR(int, pthread_spin_lock, pthread_spinlock_t *spinlock) {
740 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_spin_lock");
741 return REAL(pthread_spin_lock)(spinlock);
742}
743#define RTSAN_MAYBE_INTERCEPT_PTHREAD_SPIN_LOCK \
744 INTERCEPT_FUNCTION(pthread_spin_lock)
745#else
746#define RTSAN_MAYBE_INTERCEPT_PTHREAD_SPIN_LOCK
747#endif // SANITIZER_LINUX
748
749INTERCEPTOR(int, pthread_create, pthread_t *thread, const pthread_attr_t *attr,
750 void *(*start_routine)(void *), void *arg) {
751 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_create");
752 return REAL(pthread_create)(thread, attr, start_routine, arg);
753}
754
755INTERCEPTOR(int, pthread_mutex_lock, pthread_mutex_t *mutex) {
756 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_mutex_lock");
757 return REAL(pthread_mutex_lock)(mutex);
758}
759
760INTERCEPTOR(int, pthread_mutex_unlock, pthread_mutex_t *mutex) {
761 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_mutex_unlock");
762 return REAL(pthread_mutex_unlock)(mutex);
763}
764
765INTERCEPTOR(int, pthread_join, pthread_t thread, void **value_ptr) {
766 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_join");
767 return REAL(pthread_join)(thread, value_ptr);
768}
769
770INTERCEPTOR(int, pthread_cond_init, pthread_cond_t *cond,
771 const pthread_condattr_t *a) {
772 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_cond_init");
773 return REAL(pthread_cond_init)(cond, a);
774}
775
776INTERCEPTOR(int, pthread_cond_signal, pthread_cond_t *cond) {
777 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_cond_signal");
778 return REAL(pthread_cond_signal)(cond);
779}
780
781INTERCEPTOR(int, pthread_cond_broadcast, pthread_cond_t *cond) {
782 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_cond_broadcast");
783 return REAL(pthread_cond_broadcast)(cond);
784}
785
786INTERCEPTOR(int, pthread_cond_wait, pthread_cond_t *cond,
787 pthread_mutex_t *mutex) {
788 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_cond_wait");
789 return REAL(pthread_cond_wait)(cond, mutex);
790}
791
792INTERCEPTOR(int, pthread_cond_timedwait, pthread_cond_t *cond,
793 pthread_mutex_t *mutex, const timespec *ts) {
794 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_cond_timedwait");
795 return REAL(pthread_cond_timedwait)(cond, mutex, ts);
796}
797
798INTERCEPTOR(int, pthread_cond_destroy, pthread_cond_t *cond) {
799 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_cond_destroy");
800 return REAL(pthread_cond_destroy)(cond);
801}
802
803INTERCEPTOR(int, pthread_rwlock_rdlock, pthread_rwlock_t *lock) {
804 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_rwlock_rdlock");
805 return REAL(pthread_rwlock_rdlock)(lock);
806}
807
808INTERCEPTOR(int, pthread_rwlock_unlock, pthread_rwlock_t *lock) {
809 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_rwlock_unlock");
810 return REAL(pthread_rwlock_unlock)(lock);
811}
812
813INTERCEPTOR(int, pthread_rwlock_wrlock, pthread_rwlock_t *lock) {
814 __rtsan_notify_intercepted_call(intercepted_function_name: "pthread_rwlock_wrlock");
815 return REAL(pthread_rwlock_wrlock)(lock);
816}
817
818// Sleeping
819
820INTERCEPTOR(unsigned int, sleep, unsigned int s) {
821 __rtsan_notify_intercepted_call(intercepted_function_name: "sleep");
822 return REAL(sleep)(s);
823}
824
825INTERCEPTOR(int, usleep, useconds_t u) {
826 __rtsan_notify_intercepted_call(intercepted_function_name: "usleep");
827 return REAL(usleep)(u);
828}
829
830INTERCEPTOR(int, nanosleep, const struct timespec *rqtp,
831 struct timespec *rmtp) {
832 __rtsan_notify_intercepted_call(intercepted_function_name: "nanosleep");
833 return REAL(nanosleep)(rqtp, rmtp);
834}
835
836INTERCEPTOR(int, sched_yield, void) {
837 __rtsan_notify_intercepted_call(intercepted_function_name: "sched_yield");
838 return REAL(sched_yield)();
839}
840
841#if SANITIZER_LINUX
842INTERCEPTOR(int, sched_getaffinity, pid_t pid, size_t len, cpu_set_t *set) {
843 __rtsan_notify_intercepted_call(intercepted_function_name: "sched_getaffinity");
844 return REAL(sched_getaffinity)(pid, len, set);
845}
846
847INTERCEPTOR(int, sched_setaffinity, pid_t pid, size_t len,
848 const cpu_set_t *set) {
849 __rtsan_notify_intercepted_call(intercepted_function_name: "sched_setaffinity");
850 return REAL(sched_setaffinity)(pid, len, set);
851}
852#define RTSAN_MAYBE_INTERCEPT_SCHED_GETAFFINITY \
853 INTERCEPT_FUNCTION(sched_getaffinity)
854#define RTSAN_MAYBE_INTERCEPT_SCHED_SETAFFINITY \
855 INTERCEPT_FUNCTION(sched_setaffinity)
856#else
857#define RTSAN_MAYBE_INTERCEPT_SCHED_GETAFFINITY
858#define RTSAN_MAYBE_INTERCEPT_SCHED_SETAFFINITY
859#endif
860
861// Memory
862
863INTERCEPTOR(void *, calloc, SIZE_T num, SIZE_T size) {
864 if (DlsymAlloc::Use())
865 return DlsymAlloc::Callocate(nmemb: num, size);
866
867 __rtsan_notify_intercepted_call(intercepted_function_name: "calloc");
868 return REAL(calloc)(num, size);
869}
870
871INTERCEPTOR(void, free, void *ptr) {
872 // According to the C and C++ standard, freeing a nullptr is guaranteed to be
873 // a no-op (and thus real-time safe). This can be confirmed for looking at
874 // __libc_free in the glibc source.
875 // Crucially must be done before DlsymAlloc::Free, as it can crash on
876 // nullptr input on linux.
877 if (UNLIKELY(!ptr))
878 return;
879
880 if (DlsymAlloc::PointerIsMine(ptr))
881 return DlsymAlloc::Free(ptr);
882
883 __rtsan_notify_intercepted_call(intercepted_function_name: "free");
884
885 return REAL(free)(ptr);
886}
887
888#if SANITIZER_INTERCEPT_FREE_SIZED
889INTERCEPTOR(void, free_sized, void *ptr, SIZE_T size) {
890 // see above comment in `free` interceptor
891 if (UNLIKELY(!ptr))
892 return;
893
894 if (DlsymAlloc::PointerIsMine(ptr))
895 return DlsymAlloc::Free(ptr);
896
897 __rtsan_notify_intercepted_call(intercepted_function_name: "free_sized");
898
899 if (REAL(free_sized))
900 return REAL(free_sized)(ptr, size);
901 return REAL(free)(ptr);
902}
903#define RTSAN_MAYBE_INTERCEPT_FREE_SIZED INTERCEPT_FUNCTION(free_sized)
904#else
905#define RTSAN_MAYBE_INTERCEPT_FREE_SIZED
906#endif
907
908#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED
909INTERCEPTOR(void, free_aligned_sized, void *ptr, SIZE_T alignment,
910 SIZE_T size) {
911 // see above comment in `free` interceptor
912 if (UNLIKELY(!ptr))
913 return;
914
915 if (DlsymAlloc::PointerIsMine(ptr))
916 return DlsymAlloc::Free(ptr);
917
918 __rtsan_notify_intercepted_call(intercepted_function_name: "free_aligned_sized");
919
920 if (REAL(free_aligned_sized))
921 return REAL(free_aligned_sized)(ptr, alignment, size);
922 return REAL(free)(ptr);
923}
924#define RTSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED \
925 INTERCEPT_FUNCTION(free_aligned_sized)
926#else
927#define RTSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED
928#endif
929
930INTERCEPTOR(void *, malloc, SIZE_T size) {
931 if (DlsymAlloc::Use())
932 return DlsymAlloc::Allocate(size_in_bytes: size);
933
934 __rtsan_notify_intercepted_call(intercepted_function_name: "malloc");
935 return REAL(malloc)(size);
936}
937
938INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
939 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
940 return DlsymAlloc::Realloc(ptr, new_size: size);
941
942 __rtsan_notify_intercepted_call(intercepted_function_name: "realloc");
943 return REAL(realloc)(ptr, size);
944}
945
946INTERCEPTOR(void *, reallocf, void *ptr, SIZE_T size) {
947 __rtsan_notify_intercepted_call(intercepted_function_name: "reallocf");
948 return REAL(reallocf)(ptr, size);
949}
950
951INTERCEPTOR(void *, valloc, SIZE_T size) {
952 __rtsan_notify_intercepted_call(intercepted_function_name: "valloc");
953 return REAL(valloc)(size);
954}
955
956#if SANITIZER_INTERCEPT_ALIGNED_ALLOC
957
958// In some cases, when targeting older Darwin versions, this warning may pop up.
959// Because we are providing a wrapper, the client is responsible to check
960// whether aligned_alloc is available, not us. We still succeed linking on an
961// old OS, because we are using a weak symbol (see aligned_alloc in
962// sanitizer_platform_interceptors.h)
963#pragma clang diagnostic push
964#pragma clang diagnostic ignored "-Wunguarded-availability-new"
965INTERCEPTOR(void *, aligned_alloc, SIZE_T alignment, SIZE_T size) {
966 __rtsan_notify_intercepted_call(intercepted_function_name: "aligned_alloc");
967 return REAL(aligned_alloc)(alignment, size);
968}
969#pragma clang diagnostic pop
970#define RTSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc)
971#else
972#define RTSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC
973#endif
974
975INTERCEPTOR(int, posix_memalign, void **memptr, size_t alignment, size_t size) {
976 __rtsan_notify_intercepted_call(intercepted_function_name: "posix_memalign");
977 return REAL(posix_memalign)(memptr, alignment, size);
978}
979
980#if SANITIZER_INTERCEPT_MEMALIGN
981INTERCEPTOR(void *, memalign, size_t alignment, size_t size) {
982 __rtsan_notify_intercepted_call(intercepted_function_name: "memalign");
983 return REAL(memalign)(alignment, size);
984}
985#define RTSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
986#else
987#define RTSAN_MAYBE_INTERCEPT_MEMALIGN
988#endif
989
990#if SANITIZER_INTERCEPT_PVALLOC
991INTERCEPTOR(void *, pvalloc, size_t size) {
992 __rtsan_notify_intercepted_call(intercepted_function_name: "pvalloc");
993 return REAL(pvalloc)(size);
994}
995#define RTSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
996#else
997#define RTSAN_MAYBE_INTERCEPT_PVALLOC
998#endif
999
1000INTERCEPTOR(void *, mmap, void *addr, size_t length, int prot, int flags,
1001 int fd, off_t offset) {
1002 __rtsan_notify_intercepted_call(intercepted_function_name: "mmap");
1003 return REAL(mmap)(addr, length, prot, flags, fd, offset);
1004}
1005
1006#if SANITIZER_INTERCEPT_MMAP64
1007INTERCEPTOR(void *, mmap64, void *addr, size_t length, int prot, int flags,
1008 int fd, off64_t offset) {
1009 __rtsan_notify_intercepted_call(intercepted_function_name: "mmap64");
1010 return REAL(mmap64)(addr, length, prot, flags, fd, offset);
1011}
1012#define RTSAN_MAYBE_INTERCEPT_MMAP64 INTERCEPT_FUNCTION(mmap64)
1013#else
1014#define RTSAN_MAYBE_INTERCEPT_MMAP64
1015#endif // SANITIZER_INTERCEPT_MMAP64
1016
1017#if SANITIZER_LINUX
1018// Note that even if rtsan is ported to netbsd, it has a slighty different
1019// and non-variadic signature
1020INTERCEPTOR(void *, mremap, void *oaddr, size_t olength, size_t nlength,
1021 int flags, ...) {
1022 __rtsan_notify_intercepted_call(intercepted_function_name: "mremap");
1023
1024 // the last optional argument is only used in this case
1025 // as the new page region will be assigned to. Is ignored otherwise.
1026 if (flags & MREMAP_FIXED) {
1027 va_list args;
1028
1029 va_start(args, flags);
1030 void *naddr = va_arg(args, void *);
1031 va_end(args);
1032
1033 return REAL(mremap)(oaddr, olength, nlength, flags, naddr);
1034 }
1035
1036 return REAL(mremap)(oaddr, olength, nlength, flags);
1037}
1038#define RTSAN_MAYBE_INTERCEPT_MREMAP INTERCEPT_FUNCTION(mremap)
1039#else
1040#define RTSAN_MAYBE_INTERCEPT_MREMAP
1041#endif
1042
1043INTERCEPTOR(int, munmap, void *addr, size_t length) {
1044 __rtsan_notify_intercepted_call(intercepted_function_name: "munmap");
1045 return REAL(munmap)(addr, length);
1046}
1047
1048#if !SANITIZER_APPLE
1049INTERCEPTOR(int, madvise, void *addr, size_t length, int flag) {
1050 __rtsan_notify_intercepted_call(intercepted_function_name: "madvise");
1051 return REAL(madvise)(addr, length, flag);
1052}
1053
1054INTERCEPTOR(int, posix_madvise, void *addr, size_t length, int flag) {
1055 __rtsan_notify_intercepted_call(intercepted_function_name: "posix_madvise");
1056 return REAL(posix_madvise)(addr, length, flag);
1057}
1058#define RTSAN_MAYBE_INTERCEPT_MADVISE INTERCEPT_FUNCTION(madvise)
1059#define RTSAN_MAYBE_INTERCEPT_POSIX_MADVISE INTERCEPT_FUNCTION(posix_madvise)
1060#else
1061#define RTSAN_MAYBE_INTERCEPT_MADVISE
1062#define RTSAN_MAYBE_INTERCEPT_POSIX_MADVISE
1063#endif
1064
1065INTERCEPTOR(int, mprotect, void *addr, size_t length, int prot) {
1066 __rtsan_notify_intercepted_call(intercepted_function_name: "mprotect");
1067 return REAL(mprotect)(addr, length, prot);
1068}
1069
1070INTERCEPTOR(int, msync, void *addr, size_t length, int flag) {
1071 __rtsan_notify_intercepted_call(intercepted_function_name: "msync");
1072 return REAL(msync)(addr, length, flag);
1073}
1074
1075#if SANITIZER_APPLE
1076INTERCEPTOR(int, mincore, const void *addr, size_t length, char *vec) {
1077#else
1078INTERCEPTOR(int, mincore, void *addr, size_t length, unsigned char *vec) {
1079#endif
1080 __rtsan_notify_intercepted_call(intercepted_function_name: "mincore");
1081 return REAL(mincore)(addr, length, vec);
1082}
1083
1084INTERCEPTOR(int, shm_open, const char *name, int oflag, mode_t mode) {
1085 __rtsan_notify_intercepted_call(intercepted_function_name: "shm_open");
1086 return REAL(shm_open)(name, oflag, mode);
1087}
1088
1089INTERCEPTOR(int, shm_unlink, const char *name) {
1090 __rtsan_notify_intercepted_call(intercepted_function_name: "shm_unlink");
1091 return REAL(shm_unlink)(name);
1092}
1093
1094#if !SANITIZER_APPLE
1095// is supported by freebsd too
1096INTERCEPTOR(int, memfd_create, const char *path, unsigned int flags) {
1097 __rtsan_notify_intercepted_call(intercepted_function_name: "memfd_create");
1098 return REAL(memfd_create)(path, flags);
1099}
1100#define RTSAN_MAYBE_INTERCEPT_MEMFD_CREATE INTERCEPT_FUNCTION(memfd_create)
1101#else
1102#define RTSAN_MAYBE_INTERCEPT_MEMFD_CREATE
1103#endif
1104
1105// Sockets
1106INTERCEPTOR(int, getaddrinfo, const char *node, const char *service,
1107 const struct addrinfo *hints, struct addrinfo **res) {
1108 __rtsan_notify_intercepted_call(intercepted_function_name: "getaddrinfo");
1109 return REAL(getaddrinfo)(node, service, hints, res);
1110}
1111
1112INTERCEPTOR(int, getnameinfo, const struct sockaddr *sa, socklen_t salen,
1113 char *host, socklen_t hostlen, char *serv, socklen_t servlen,
1114 int flags) {
1115 __rtsan_notify_intercepted_call(intercepted_function_name: "getnameinfo");
1116 return REAL(getnameinfo)(sa, salen, host, hostlen, serv, servlen, flags);
1117}
1118
1119#if SANITIZER_INTERCEPT_GETSOCKNAME
1120INTERCEPTOR(int, getsockname, int socket, struct sockaddr *sa,
1121 socklen_t *salen) {
1122 __rtsan_notify_intercepted_call(intercepted_function_name: "getsockname");
1123 return REAL(getsockname)(socket, sa, salen);
1124}
1125#define RTSAN_MAYBE_INTERCEPT_GETSOCKNAME INTERCEPT_FUNCTION(getsockname)
1126#else
1127#define RTSAN_MAYBE_INTERCEPT_GETSOCKNAME
1128#endif
1129
1130#if SANITIZER_INTERCEPT_GETPEERNAME
1131INTERCEPTOR(int, getpeername, int socket, struct sockaddr *sa,
1132 socklen_t *salen) {
1133 __rtsan_notify_intercepted_call(intercepted_function_name: "getpeername");
1134 return REAL(getpeername)(socket, sa, salen);
1135}
1136#define RTSAN_MAYBE_INTERCEPT_GETPEERNAME INTERCEPT_FUNCTION(getpeername)
1137#else
1138#define RTSAN_MAYBE_INTERCEPT_GETPEERNAME
1139#endif
1140
1141INTERCEPTOR(int, bind, int socket, const struct sockaddr *address,
1142 socklen_t address_len) {
1143 __rtsan_notify_intercepted_call(intercepted_function_name: "bind");
1144 return REAL(bind)(socket, address, address_len);
1145}
1146
1147INTERCEPTOR(int, listen, int socket, int backlog) {
1148 __rtsan_notify_intercepted_call(intercepted_function_name: "listen");
1149 return REAL(listen)(socket, backlog);
1150}
1151
1152INTERCEPTOR(int, accept, int socket, struct sockaddr *address,
1153 socklen_t *address_len) {
1154 __rtsan_notify_intercepted_call(intercepted_function_name: "accept");
1155 return REAL(accept)(socket, address, address_len);
1156}
1157
1158INTERCEPTOR(int, connect, int socket, const struct sockaddr *address,
1159 socklen_t address_len) {
1160 __rtsan_notify_intercepted_call(intercepted_function_name: "connect");
1161 return REAL(connect)(socket, address, address_len);
1162}
1163
1164INTERCEPTOR(int, socket, int domain, int type, int protocol) {
1165 __rtsan_notify_intercepted_call(intercepted_function_name: "socket");
1166 return REAL(socket)(domain, type, protocol);
1167}
1168
1169INTERCEPTOR(ssize_t, send, int sockfd, const void *buf, size_t len, int flags) {
1170 __rtsan_notify_intercepted_call(intercepted_function_name: "send");
1171 return REAL(send)(sockfd, buf, len, flags);
1172}
1173
1174INTERCEPTOR(ssize_t, sendmsg, int socket, const struct msghdr *message,
1175 int flags) {
1176 __rtsan_notify_intercepted_call(intercepted_function_name: "sendmsg");
1177 return REAL(sendmsg)(socket, message, flags);
1178}
1179
1180#if SANITIZER_INTERCEPT_SENDMMSG
1181#if SANITIZER_MUSL
1182INTERCEPTOR(int, sendmmsg, int socket, struct mmsghdr *message,
1183 unsigned int len, unsigned int flags) {
1184#else
1185INTERCEPTOR(int, sendmmsg, int socket, struct mmsghdr *message,
1186 unsigned int len, int flags) {
1187#endif
1188 __rtsan_notify_intercepted_call(intercepted_function_name: "sendmmsg");
1189 return REAL(sendmmsg)(socket, message, len, flags);
1190}
1191#define RTSAN_MAYBE_INTERCEPT_SENDMMSG INTERCEPT_FUNCTION(sendmmsg)
1192#else
1193#define RTSAN_MAYBE_INTERCEPT_SENDMMSG
1194#endif
1195
1196INTERCEPTOR(ssize_t, sendto, int socket, const void *buffer, size_t length,
1197 int flags, const struct sockaddr *dest_addr, socklen_t dest_len) {
1198 __rtsan_notify_intercepted_call(intercepted_function_name: "sendto");
1199 return REAL(sendto)(socket, buffer, length, flags, dest_addr, dest_len);
1200}
1201
1202INTERCEPTOR(ssize_t, recv, int socket, void *buffer, size_t length, int flags) {
1203 __rtsan_notify_intercepted_call(intercepted_function_name: "recv");
1204 return REAL(recv)(socket, buffer, length, flags);
1205}
1206
1207INTERCEPTOR(ssize_t, recvfrom, int socket, void *buffer, size_t length,
1208 int flags, struct sockaddr *address, socklen_t *address_len) {
1209 __rtsan_notify_intercepted_call(intercepted_function_name: "recvfrom");
1210 return REAL(recvfrom)(socket, buffer, length, flags, address, address_len);
1211}
1212
1213INTERCEPTOR(ssize_t, recvmsg, int socket, struct msghdr *message, int flags) {
1214 __rtsan_notify_intercepted_call(intercepted_function_name: "recvmsg");
1215 return REAL(recvmsg)(socket, message, flags);
1216}
1217
1218#if SANITIZER_INTERCEPT_RECVMMSG
1219#if SANITIZER_MUSL
1220INTERCEPTOR(int, recvmmsg, int socket, struct mmsghdr *message,
1221 unsigned int len, unsigned int flags, struct timespec *timeout) {
1222#elif defined(__GLIBC_MINOR__) && __GLIBC_MINOR__ < 21
1223INTERCEPTOR(int, recvmmsg, int socket, struct mmsghdr *message,
1224 unsigned int len, int flags, const struct timespec *timeout) {
1225#else
1226INTERCEPTOR(int, recvmmsg, int socket, struct mmsghdr *message,
1227 unsigned int len, int flags, struct timespec *timeout) {
1228#endif // defined(__GLIBC_MINOR) && __GLIBC_MINOR__ < 21
1229 __rtsan_notify_intercepted_call(intercepted_function_name: "recvmmsg");
1230 return REAL(recvmmsg)(socket, message, len, flags, timeout);
1231}
1232#define RTSAN_MAYBE_INTERCEPT_RECVMMSG INTERCEPT_FUNCTION(recvmmsg)
1233#else
1234#define RTSAN_MAYBE_INTERCEPT_RECVMMSG
1235#endif
1236
1237INTERCEPTOR(int, shutdown, int socket, int how) {
1238 __rtsan_notify_intercepted_call(intercepted_function_name: "shutdown");
1239 return REAL(shutdown)(socket, how);
1240}
1241
1242#if SANITIZER_INTERCEPT_ACCEPT4
1243INTERCEPTOR(int, accept4, int socket, struct sockaddr *address,
1244 socklen_t *address_len, int flags) {
1245 __rtsan_notify_intercepted_call(intercepted_function_name: "accept4");
1246 return REAL(accept4)(socket, address, address_len, flags);
1247}
1248#define RTSAN_MAYBE_INTERCEPT_ACCEPT4 INTERCEPT_FUNCTION(accept4)
1249#else
1250#define RTSAN_MAYBE_INTERCEPT_ACCEPT4
1251#endif
1252
1253#if SANITIZER_INTERCEPT_GETSOCKOPT
1254INTERCEPTOR(int, getsockopt, int socket, int level, int option, void *value,
1255 socklen_t *len) {
1256 __rtsan_notify_intercepted_call(intercepted_function_name: "getsockopt");
1257 return REAL(getsockopt)(socket, level, option, value, len);
1258}
1259
1260INTERCEPTOR(int, setsockopt, int socket, int level, int option,
1261 const void *value, socklen_t len) {
1262 __rtsan_notify_intercepted_call(intercepted_function_name: "setsockopt");
1263 return REAL(setsockopt)(socket, level, option, value, len);
1264}
1265#define RTSAN_MAYBE_INTERCEPT_GETSOCKOPT INTERCEPT_FUNCTION(getsockopt)
1266#define RTSAN_MAYBE_INTERCEPT_SETSOCKOPT INTERCEPT_FUNCTION(setsockopt)
1267#else
1268#define RTSAN_MAYBE_INTERCEPT_GETSOCKOPT
1269#define RTSAN_MAYBE_INTERCEPT_SETSOCKOPT
1270#endif
1271
1272INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int pair[2]) {
1273 __rtsan_notify_intercepted_call(intercepted_function_name: "socketpair");
1274 return REAL(socketpair)(domain, type, protocol, pair);
1275}
1276
1277// I/O Multiplexing
1278
1279INTERCEPTOR(int, poll, struct pollfd *fds, nfds_t nfds, int timeout) {
1280 __rtsan_notify_intercepted_call(intercepted_function_name: "poll");
1281 return REAL(poll)(fds, nfds, timeout);
1282}
1283
1284#if !SANITIZER_APPLE
1285// FIXME: This should work on all unix systems, even Mac, but currently
1286// it is showing some weird error while linking
1287// error: declaration of 'select' has a different language linkage
1288INTERCEPTOR(int, select, int nfds, fd_set *readfds, fd_set *writefds,
1289 fd_set *exceptfds, struct timeval *timeout) {
1290 __rtsan_notify_intercepted_call(intercepted_function_name: "select");
1291 return REAL(select)(nfds, readfds, writefds, exceptfds, timeout);
1292}
1293#define RTSAN_MAYBE_INTERCEPT_SELECT INTERCEPT_FUNCTION(select)
1294#else
1295#define RTSAN_MAYBE_INTERCEPT_SELECT
1296#endif // !SANITIZER_APPLE
1297
1298INTERCEPTOR(int, pselect, int nfds, fd_set *readfds, fd_set *writefds,
1299 fd_set *exceptfds, const struct timespec *timeout,
1300 const sigset_t *sigmask) {
1301 __rtsan_notify_intercepted_call(intercepted_function_name: "pselect");
1302 return REAL(pselect)(nfds, readfds, writefds, exceptfds, timeout, sigmask);
1303}
1304
1305#if SANITIZER_INTERCEPT_EPOLL
1306INTERCEPTOR(int, epoll_create, int size) {
1307 __rtsan_notify_intercepted_call(intercepted_function_name: "epoll_create");
1308 return REAL(epoll_create)(size);
1309}
1310
1311INTERCEPTOR(int, epoll_create1, int flags) {
1312 __rtsan_notify_intercepted_call(intercepted_function_name: "epoll_create1");
1313 return REAL(epoll_create1)(flags);
1314}
1315
1316INTERCEPTOR(int, epoll_ctl, int epfd, int op, int fd,
1317 struct epoll_event *event) {
1318 __rtsan_notify_intercepted_call(intercepted_function_name: "epoll_ctl");
1319 return REAL(epoll_ctl)(epfd, op, fd, event);
1320}
1321
1322INTERCEPTOR(int, epoll_wait, int epfd, struct epoll_event *events,
1323 int maxevents, int timeout) {
1324 __rtsan_notify_intercepted_call(intercepted_function_name: "epoll_wait");
1325 return REAL(epoll_wait)(epfd, events, maxevents, timeout);
1326}
1327
1328INTERCEPTOR(int, epoll_pwait, int epfd, struct epoll_event *events,
1329 int maxevents, int timeout, const sigset_t *sigmask) {
1330 __rtsan_notify_intercepted_call(intercepted_function_name: "epoll_pwait");
1331 return REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
1332}
1333#define RTSAN_MAYBE_INTERCEPT_EPOLL_CREATE INTERCEPT_FUNCTION(epoll_create)
1334#define RTSAN_MAYBE_INTERCEPT_EPOLL_CREATE1 INTERCEPT_FUNCTION(epoll_create1)
1335#define RTSAN_MAYBE_INTERCEPT_EPOLL_CTL INTERCEPT_FUNCTION(epoll_ctl)
1336#define RTSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
1337#define RTSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
1338#else
1339#define RTSAN_MAYBE_INTERCEPT_EPOLL_CREATE
1340#define RTSAN_MAYBE_INTERCEPT_EPOLL_CREATE1
1341#define RTSAN_MAYBE_INTERCEPT_EPOLL_CTL
1342#define RTSAN_MAYBE_INTERCEPT_EPOLL_WAIT
1343#define RTSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
1344#endif // SANITIZER_INTERCEPT_EPOLL
1345
1346#if SANITIZER_INTERCEPT_PPOLL
1347INTERCEPTOR(int, ppoll, struct pollfd *fds, nfds_t n, const struct timespec *ts,
1348 const sigset_t *set) {
1349 __rtsan_notify_intercepted_call(intercepted_function_name: "ppoll");
1350 return REAL(ppoll)(fds, n, ts, set);
1351}
1352#define RTSAN_MAYBE_INTERCEPT_PPOLL INTERCEPT_FUNCTION(ppoll)
1353#else
1354#define RTSAN_MAYBE_INTERCEPT_PPOLL
1355#endif
1356
1357#if SANITIZER_INTERCEPT_KQUEUE
1358INTERCEPTOR(int, kqueue, void) {
1359 __rtsan_notify_intercepted_call("kqueue");
1360 return REAL(kqueue)();
1361}
1362
1363INTERCEPTOR(int, kevent, int kq, const struct kevent *changelist, int nchanges,
1364 struct kevent *eventlist, int nevents,
1365 const struct timespec *timeout) {
1366 __rtsan_notify_intercepted_call("kevent");
1367 return REAL(kevent)(kq, changelist, nchanges, eventlist, nevents, timeout);
1368}
1369
1370INTERCEPTOR(int, kevent64, int kq, const struct kevent64_s *changelist,
1371 int nchanges, struct kevent64_s *eventlist, int nevents,
1372 unsigned int flags, const struct timespec *timeout) {
1373 __rtsan_notify_intercepted_call("kevent64");
1374 return REAL(kevent64)(kq, changelist, nchanges, eventlist, nevents, flags,
1375 timeout);
1376}
1377#define RTSAN_MAYBE_INTERCEPT_KQUEUE INTERCEPT_FUNCTION(kqueue)
1378#define RTSAN_MAYBE_INTERCEPT_KEVENT INTERCEPT_FUNCTION(kevent)
1379#define RTSAN_MAYBE_INTERCEPT_KEVENT64 INTERCEPT_FUNCTION(kevent64)
1380#else
1381#define RTSAN_MAYBE_INTERCEPT_KQUEUE
1382#define RTSAN_MAYBE_INTERCEPT_KEVENT
1383#define RTSAN_MAYBE_INTERCEPT_KEVENT64
1384#endif // SANITIZER_INTERCEPT_KQUEUE
1385
1386#if SANITIZER_LINUX
1387INTERCEPTOR(int, inotify_init) {
1388 __rtsan_notify_intercepted_call(intercepted_function_name: "inotify_init");
1389 return REAL(inotify_init)();
1390}
1391
1392INTERCEPTOR(int, inotify_init1, int flags) {
1393 __rtsan_notify_intercepted_call(intercepted_function_name: "inotify_init1");
1394 return REAL(inotify_init1)(flags);
1395}
1396
1397INTERCEPTOR(int, inotify_add_watch, int fd, const char *path, uint32_t mask) {
1398 __rtsan_notify_intercepted_call(intercepted_function_name: "inotify_add_watch");
1399 return REAL(inotify_add_watch)(fd, path, mask);
1400}
1401
1402INTERCEPTOR(int, inotify_rm_watch, int fd, int wd) {
1403 __rtsan_notify_intercepted_call(intercepted_function_name: "inotify_rm_watch");
1404 return REAL(inotify_rm_watch)(fd, wd);
1405}
1406
1407INTERCEPTOR(int, timerfd_create, int clockid, int flags) {
1408 __rtsan_notify_intercepted_call(intercepted_function_name: "timerfd_create");
1409 return REAL(timerfd_create)(clockid, flags);
1410}
1411
1412INTERCEPTOR(int, timerfd_settime, int fd, int flags, const itimerspec *newval,
1413 struct itimerspec *oldval) {
1414 __rtsan_notify_intercepted_call(intercepted_function_name: "timerfd_settime");
1415 return REAL(timerfd_settime)(fd, flags, newval, oldval);
1416}
1417
1418INTERCEPTOR(int, timerfd_gettime, int fd, struct itimerspec *val) {
1419 __rtsan_notify_intercepted_call(intercepted_function_name: "timerfd_gettime");
1420 return REAL(timerfd_gettime)(fd, val);
1421}
1422
1423/* eventfd wrappers calls SYS_eventfd2 down the line */
1424INTERCEPTOR(int, eventfd, unsigned int count, int flags) {
1425 __rtsan_notify_intercepted_call(intercepted_function_name: "eventfd");
1426 return REAL(eventfd)(count, flags);
1427}
1428#define RTSAN_MAYBE_INTERCEPT_INOTIFY_INIT INTERCEPT_FUNCTION(inotify_init)
1429#define RTSAN_MAYBE_INTERCEPT_INOTIFY_INIT1 INTERCEPT_FUNCTION(inotify_init1)
1430#define RTSAN_MAYBE_INTERCEPT_INOTIFY_ADD_WATCH \
1431 INTERCEPT_FUNCTION(inotify_add_watch)
1432#define RTSAN_MAYBE_INTERCEPT_INOTIFY_RM_WATCH \
1433 INTERCEPT_FUNCTION(inotify_rm_watch)
1434#define RTSAN_MAYBE_INTERCEPT_TIMERFD_CREATE INTERCEPT_FUNCTION(timerfd_create)
1435#define RTSAN_MAYBE_INTERCEPT_TIMERFD_SETTIME \
1436 INTERCEPT_FUNCTION(timerfd_settime)
1437#define RTSAN_MAYBE_INTERCEPT_TIMERFD_GETTIME \
1438 INTERCEPT_FUNCTION(timerfd_gettime)
1439#define RTSAN_MAYBE_INTERCEPT_EVENTFD INTERCEPT_FUNCTION(eventfd)
1440#else
1441#define RTSAN_MAYBE_INTERCEPT_INOTIFY_INIT
1442#define RTSAN_MAYBE_INTERCEPT_INOTIFY_INIT1
1443#define RTSAN_MAYBE_INTERCEPT_INOTIFY_ADD_WATCH
1444#define RTSAN_MAYBE_INTERCEPT_INOTIFY_RM_WATCH
1445#define RTSAN_MAYBE_INTERCEPT_TIMERFD_CREATE
1446#define RTSAN_MAYBE_INTERCEPT_TIMERFD_SETTIME
1447#define RTSAN_MAYBE_INTERCEPT_TIMERFD_GETTIME
1448#define RTSAN_MAYBE_INTERCEPT_EVENTFD
1449#endif
1450
1451INTERCEPTOR(int, pipe, int pipefd[2]) {
1452 __rtsan_notify_intercepted_call(intercepted_function_name: "pipe");
1453 return REAL(pipe)(pipefd);
1454}
1455
1456#if !SANITIZER_APPLE
1457INTERCEPTOR(int, pipe2, int pipefd[2], int flags) {
1458 __rtsan_notify_intercepted_call(intercepted_function_name: "pipe2");
1459 return REAL(pipe2)(pipefd, flags);
1460}
1461#define RTSAN_MAYBE_INTERCEPT_PIPE2 INTERCEPT_FUNCTION(pipe2)
1462#else
1463#define RTSAN_MAYBE_INTERCEPT_PIPE2
1464#endif
1465
1466INTERCEPTOR(int, mkfifo, const char *pathname, mode_t mode) {
1467 __rtsan_notify_intercepted_call(intercepted_function_name: "mkfifo");
1468 return REAL(mkfifo)(pathname, mode);
1469}
1470
1471INTERCEPTOR(pid_t, fork, void) {
1472 __rtsan_notify_intercepted_call(intercepted_function_name: "fork");
1473 return REAL(fork)();
1474}
1475
1476INTERCEPTOR(int, execve, const char *filename, char *const argv[],
1477 char *const envp[]) {
1478 __rtsan_notify_intercepted_call(intercepted_function_name: "execve");
1479 return REAL(execve)(filename, argv, envp);
1480}
1481
1482#if SANITIZER_INTERCEPT_PROCESS_VM_READV
1483INTERCEPTOR(ssize_t, process_vm_readv, pid_t pid, const struct iovec *local_iov,
1484 unsigned long liovcnt, const struct iovec *remote_iov,
1485 unsigned long riovcnt, unsigned long flags) {
1486 __rtsan_notify_intercepted_call(intercepted_function_name: "process_vm_readv");
1487 return REAL(process_vm_readv)(pid, local_iov, liovcnt, remote_iov, riovcnt,
1488 flags);
1489}
1490
1491INTERCEPTOR(ssize_t, process_vm_writev, pid_t pid,
1492 const struct iovec *local_iov, unsigned long liovcnt,
1493 const struct iovec *remote_iov, unsigned long riovcnt,
1494 unsigned long flags) {
1495 __rtsan_notify_intercepted_call(intercepted_function_name: "process_vm_writev");
1496 return REAL(process_vm_writev)(pid, local_iov, liovcnt, remote_iov, riovcnt,
1497 flags);
1498}
1499#define RTSAN_MAYBE_INTERCEPT_PROCESS_VM_READV \
1500 INTERCEPT_FUNCTION(process_vm_readv)
1501#define RTSAN_MAYBE_INTERCEPT_PROCESS_VM_WRITEV \
1502 INTERCEPT_FUNCTION(process_vm_writev)
1503#else
1504#define RTSAN_MAYBE_INTERCEPT_PROCESS_VM_READV
1505#define RTSAN_MAYBE_INTERCEPT_PROCESS_VM_WRITEV
1506#endif
1507
1508// TODO: the `wait` family of functions is an oddity. In testing, if you
1509// intercept them, Darwin seemingly ignores them, and linux never returns from
1510// the test. Revisit this in the future, but hopefully intercepting fork/exec is
1511// enough to dissuade usage of wait by proxy.
1512
1513#if SANITIZER_APPLE
1514#define INT_TYPE_SYSCALL int
1515#else
1516#define INT_TYPE_SYSCALL long
1517#endif
1518
1519#pragma clang diagnostic push
1520#pragma clang diagnostic ignored "-Wdeprecated-declarations"
1521INTERCEPTOR(INT_TYPE_SYSCALL, syscall, INT_TYPE_SYSCALL number, ...) {
1522 __rtsan_notify_intercepted_call(intercepted_function_name: "syscall");
1523
1524 va_list args;
1525 va_start(args, number);
1526
1527 // the goal is to pick something large enough to hold all syscall args
1528 // see fcntl for more discussion and why we always pull all 6 args
1529 using arg_type = unsigned long;
1530 arg_type arg1 = va_arg(args, arg_type);
1531 arg_type arg2 = va_arg(args, arg_type);
1532 arg_type arg3 = va_arg(args, arg_type);
1533 arg_type arg4 = va_arg(args, arg_type);
1534 arg_type arg5 = va_arg(args, arg_type);
1535 arg_type arg6 = va_arg(args, arg_type);
1536
1537 // these are various examples of things that COULD be passed
1538 // On 32-bit platforms, 64-bit types like off_t are split across two args.
1539#if SANITIZER_WORDSIZE >= 64
1540 static_assert(sizeof(arg_type) >= sizeof(off_t));
1541#endif
1542 static_assert(sizeof(arg_type) >= sizeof(struct flock *));
1543 static_assert(sizeof(arg_type) >= sizeof(const char *));
1544 static_assert(sizeof(arg_type) >= sizeof(int));
1545 static_assert(sizeof(arg_type) >= sizeof(unsigned long));
1546
1547 va_end(args);
1548
1549 return REAL(syscall)(number, arg1, arg2, arg3, arg4, arg5, arg6);
1550}
1551#pragma clang diagnostic pop
1552
1553// Preinit
1554void __rtsan::InitializeInterceptors() {
1555 INTERCEPT_FUNCTION(calloc);
1556 INTERCEPT_FUNCTION(free);
1557 RTSAN_MAYBE_INTERCEPT_FREE_SIZED;
1558 RTSAN_MAYBE_INTERCEPT_FREE_ALIGNED_SIZED;
1559 INTERCEPT_FUNCTION(malloc);
1560 INTERCEPT_FUNCTION(realloc);
1561 INTERCEPT_FUNCTION(reallocf);
1562 INTERCEPT_FUNCTION(valloc);
1563 RTSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC;
1564 INTERCEPT_FUNCTION(posix_memalign);
1565 INTERCEPT_FUNCTION(mmap);
1566 RTSAN_MAYBE_INTERCEPT_MMAP64;
1567 RTSAN_MAYBE_INTERCEPT_MREMAP;
1568 INTERCEPT_FUNCTION(munmap);
1569 RTSAN_MAYBE_INTERCEPT_MADVISE;
1570 RTSAN_MAYBE_INTERCEPT_POSIX_MADVISE;
1571 INTERCEPT_FUNCTION(mprotect);
1572 INTERCEPT_FUNCTION(msync);
1573 INTERCEPT_FUNCTION(mincore);
1574 INTERCEPT_FUNCTION(shm_open);
1575 INTERCEPT_FUNCTION(shm_unlink);
1576 RTSAN_MAYBE_INTERCEPT_MEMFD_CREATE;
1577 RTSAN_MAYBE_INTERCEPT_MEMALIGN;
1578 RTSAN_MAYBE_INTERCEPT_PVALLOC;
1579
1580 INTERCEPT_FUNCTION(open);
1581 RTSAN_MAYBE_INTERCEPT_OPEN64;
1582 INTERCEPT_FUNCTION(openat);
1583 RTSAN_MAYBE_INTERCEPT_OPENAT64;
1584 INTERCEPT_FUNCTION(close);
1585 INTERCEPT_FUNCTION(chdir);
1586 INTERCEPT_FUNCTION(fchdir);
1587 RTSAN_MAYBE_INTERCEPT_READLINK;
1588 RTSAN_MAYBE_INTERCEPT_READLINKAT;
1589 INTERCEPT_FUNCTION(unlink);
1590 INTERCEPT_FUNCTION(unlinkat);
1591 INTERCEPT_FUNCTION(symlink);
1592 INTERCEPT_FUNCTION(symlinkat);
1593 INTERCEPT_FUNCTION(truncate);
1594 INTERCEPT_FUNCTION(ftruncate);
1595 RTSAN_MAYBE_INTERCEPT_TRUNCATE64;
1596 RTSAN_MAYBE_INTERCEPT_FTRUNCATE64;
1597 INTERCEPT_FUNCTION(fopen);
1598 RTSAN_MAYBE_INTERCEPT_FOPEN64;
1599 RTSAN_MAYBE_INTERCEPT_FREOPEN64;
1600 INTERCEPT_FUNCTION(fread);
1601 INTERCEPT_FUNCTION(read);
1602 INTERCEPT_FUNCTION(write);
1603 INTERCEPT_FUNCTION(pread);
1604 RTSAN_MAYBE_INTERCEPT_PREAD64;
1605 RTSAN_MAYBE_INTERCEPT_PREADV;
1606 RTSAN_MAYBE_INTERCEPT_PREADV64;
1607 INTERCEPT_FUNCTION(readv);
1608 INTERCEPT_FUNCTION(pwrite);
1609 RTSAN_MAYBE_INTERCEPT_PWRITE64;
1610 RTSAN_MAYBE_INTERCEPT_PWRITEV;
1611 RTSAN_MAYBE_INTERCEPT_PWRITEV64;
1612 INTERCEPT_FUNCTION(writev);
1613 INTERCEPT_FUNCTION(fwrite);
1614 INTERCEPT_FUNCTION(fclose);
1615 INTERCEPT_FUNCTION(fcntl);
1616 RTSAN_MAYBE_INTERCEPT_FCNTL64;
1617 INTERCEPT_FUNCTION(creat);
1618 RTSAN_MAYBE_INTERCEPT_CREAT64;
1619 INTERCEPT_FUNCTION(puts);
1620 INTERCEPT_FUNCTION(fputs);
1621 INTERCEPT_FUNCTION(fflush);
1622 RTSAN_MAYBE_INTERCEPT_FPURGE;
1623 RTSAN_MAYBE_INTERCEPT_PIPE2;
1624 INTERCEPT_FUNCTION(fdopen);
1625 INTERCEPT_FUNCTION(freopen);
1626 RTSAN_MAYBE_INTERCEPT_FOPENCOOKIE;
1627 RTSAN_MAYBE_INTERCEPT_OPEN_MEMSTREAM;
1628 RTSAN_MAYBE_INTERCEPT_FMEMOPEN;
1629 RTSAN_MAYBE_INTERCEPT_SETBUF;
1630 RTSAN_MAYBE_INTERCEPT_SETVBUF;
1631 RTSAN_MAYBE_INTERCEPT_SETLINEBUF;
1632 RTSAN_MAYBE_INTERCEPT_SETBUFFER;
1633 RTSAN_MAYBE_INTERCEPT_FGETPOS;
1634 RTSAN_MAYBE_INTERCEPT_FSEEK;
1635 RTSAN_MAYBE_INTERCEPT_FSEEKO;
1636 RTSAN_MAYBE_INTERCEPT_FSETPOS;
1637 RTSAN_MAYBE_INTERCEPT_FTELL;
1638 RTSAN_MAYBE_INTERCEPT_FTELLO;
1639 RTSAN_MAYBE_INTERCEPT_REWIND;
1640 RTSAN_MAYBE_INTERCEPT_FGETPOS64;
1641 RTSAN_MAYBE_INTERCEPT_FSEEKO64;
1642 RTSAN_MAYBE_INTERCEPT_FSETPOS64;
1643 RTSAN_MAYBE_INTERCEPT_FTELLO64;
1644 INTERCEPT_FUNCTION(lseek);
1645 RTSAN_MAYBE_INTERCEPT_LSEEK64;
1646 INTERCEPT_FUNCTION(dup);
1647 INTERCEPT_FUNCTION(dup2);
1648 INTERCEPT_FUNCTION(chmod);
1649 INTERCEPT_FUNCTION(fchmod);
1650 INTERCEPT_FUNCTION(mkdir);
1651 INTERCEPT_FUNCTION(rmdir);
1652 INTERCEPT_FUNCTION(umask);
1653 INTERCEPT_FUNCTION(ioctl);
1654
1655 RTSAN_MAYBE_INTERCEPT_OSSPINLOCKLOCK;
1656 RTSAN_MAYBE_INTERCEPT_OS_UNFAIR_LOCK_LOCK;
1657 RTSAN_MAYBE_INTERCEPT_PTHREAD_SPIN_LOCK;
1658
1659 INTERCEPT_FUNCTION(pthread_create);
1660 INTERCEPT_FUNCTION(pthread_mutex_lock);
1661 INTERCEPT_FUNCTION(pthread_mutex_unlock);
1662 INTERCEPT_FUNCTION(pthread_join);
1663
1664 // See the comment in tsan_interceptors_posix.cpp.
1665#if SANITIZER_GLIBC && !__GLIBC_PREREQ(2, 36) && \
1666 (defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \
1667 defined(__s390x__))
1668 INTERCEPT_FUNCTION_VER(pthread_cond_init, "GLIBC_2.3.2");
1669 INTERCEPT_FUNCTION_VER(pthread_cond_signal, "GLIBC_2.3.2");
1670 INTERCEPT_FUNCTION_VER(pthread_cond_broadcast, "GLIBC_2.3.2");
1671 INTERCEPT_FUNCTION_VER(pthread_cond_wait, "GLIBC_2.3.2");
1672 INTERCEPT_FUNCTION_VER(pthread_cond_timedwait, "GLIBC_2.3.2");
1673 INTERCEPT_FUNCTION_VER(pthread_cond_destroy, "GLIBC_2.3.2");
1674#else
1675 INTERCEPT_FUNCTION(pthread_cond_init);
1676 INTERCEPT_FUNCTION(pthread_cond_signal);
1677 INTERCEPT_FUNCTION(pthread_cond_broadcast);
1678 INTERCEPT_FUNCTION(pthread_cond_wait);
1679 INTERCEPT_FUNCTION(pthread_cond_timedwait);
1680 INTERCEPT_FUNCTION(pthread_cond_destroy);
1681#endif
1682
1683 INTERCEPT_FUNCTION(pthread_rwlock_rdlock);
1684 INTERCEPT_FUNCTION(pthread_rwlock_unlock);
1685 INTERCEPT_FUNCTION(pthread_rwlock_wrlock);
1686
1687 INTERCEPT_FUNCTION(sleep);
1688 INTERCEPT_FUNCTION(usleep);
1689 INTERCEPT_FUNCTION(nanosleep);
1690 INTERCEPT_FUNCTION(sched_yield);
1691 RTSAN_MAYBE_INTERCEPT_SCHED_GETAFFINITY;
1692 RTSAN_MAYBE_INTERCEPT_SCHED_SETAFFINITY;
1693
1694 INTERCEPT_FUNCTION(accept);
1695 INTERCEPT_FUNCTION(bind);
1696 INTERCEPT_FUNCTION(connect);
1697 INTERCEPT_FUNCTION(getaddrinfo);
1698 INTERCEPT_FUNCTION(getnameinfo);
1699 INTERCEPT_FUNCTION(listen);
1700 INTERCEPT_FUNCTION(recv);
1701 INTERCEPT_FUNCTION(recvfrom);
1702 INTERCEPT_FUNCTION(recvmsg);
1703 RTSAN_MAYBE_INTERCEPT_RECVMMSG;
1704 INTERCEPT_FUNCTION(send);
1705 INTERCEPT_FUNCTION(sendmsg);
1706 RTSAN_MAYBE_INTERCEPT_SENDMMSG;
1707 INTERCEPT_FUNCTION(sendto);
1708 INTERCEPT_FUNCTION(shutdown);
1709 INTERCEPT_FUNCTION(socket);
1710 RTSAN_MAYBE_INTERCEPT_ACCEPT4;
1711 RTSAN_MAYBE_INTERCEPT_GETSOCKNAME;
1712 RTSAN_MAYBE_INTERCEPT_GETPEERNAME;
1713 RTSAN_MAYBE_INTERCEPT_GETSOCKOPT;
1714 RTSAN_MAYBE_INTERCEPT_SETSOCKOPT;
1715 INTERCEPT_FUNCTION(socketpair);
1716
1717 RTSAN_MAYBE_INTERCEPT_SELECT;
1718 INTERCEPT_FUNCTION(pselect);
1719 INTERCEPT_FUNCTION(poll);
1720 RTSAN_MAYBE_INTERCEPT_EPOLL_CREATE;
1721 RTSAN_MAYBE_INTERCEPT_EPOLL_CREATE1;
1722 RTSAN_MAYBE_INTERCEPT_EPOLL_CTL;
1723 RTSAN_MAYBE_INTERCEPT_EPOLL_WAIT;
1724 RTSAN_MAYBE_INTERCEPT_EPOLL_PWAIT;
1725 RTSAN_MAYBE_INTERCEPT_PPOLL;
1726 RTSAN_MAYBE_INTERCEPT_KQUEUE;
1727 RTSAN_MAYBE_INTERCEPT_KEVENT;
1728 RTSAN_MAYBE_INTERCEPT_KEVENT64;
1729
1730 RTSAN_MAYBE_INTERCEPT_INOTIFY_INIT;
1731 RTSAN_MAYBE_INTERCEPT_INOTIFY_INIT1;
1732 RTSAN_MAYBE_INTERCEPT_INOTIFY_ADD_WATCH;
1733 RTSAN_MAYBE_INTERCEPT_INOTIFY_RM_WATCH;
1734
1735 RTSAN_MAYBE_INTERCEPT_TIMERFD_CREATE;
1736 RTSAN_MAYBE_INTERCEPT_TIMERFD_SETTIME;
1737 RTSAN_MAYBE_INTERCEPT_TIMERFD_GETTIME;
1738 RTSAN_MAYBE_INTERCEPT_EVENTFD;
1739
1740 INTERCEPT_FUNCTION(pipe);
1741 INTERCEPT_FUNCTION(mkfifo);
1742
1743 INTERCEPT_FUNCTION(fork);
1744 INTERCEPT_FUNCTION(execve);
1745
1746 RTSAN_MAYBE_INTERCEPT_PROCESS_VM_READV;
1747 RTSAN_MAYBE_INTERCEPT_PROCESS_VM_WRITEV;
1748
1749 INTERCEPT_FUNCTION(syscall);
1750}
1751
1752#endif // SANITIZER_POSIX
1753