2013-01-18 21:01:18 +08:00
|
|
|
//===-- sanitizer_common_interceptors.inc -----------------------*- C++ -*-===//
|
2012-12-12 17:54:35 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Common function interceptors for tools like AddressSanitizer,
|
|
|
|
// ThreadSanitizer, MemorySanitizer, etc.
|
|
|
|
//
|
|
|
|
// This file should be included into the tool's interceptor file,
|
2016-03-11 08:45:49 +08:00
|
|
|
// which has to define its own macros:
|
2012-12-12 17:54:35 +08:00
|
|
|
// COMMON_INTERCEPTOR_ENTER
|
2014-06-06 20:16:26 +08:00
|
|
|
// COMMON_INTERCEPTOR_ENTER_NOIGNORE
|
2012-12-12 17:54:35 +08:00
|
|
|
// COMMON_INTERCEPTOR_READ_RANGE
|
|
|
|
// COMMON_INTERCEPTOR_WRITE_RANGE
|
2013-10-03 22:12:09 +08:00
|
|
|
// COMMON_INTERCEPTOR_INITIALIZE_RANGE
|
2015-01-21 16:54:01 +08:00
|
|
|
// COMMON_INTERCEPTOR_DIR_ACQUIRE
|
2013-01-17 21:09:00 +08:00
|
|
|
// COMMON_INTERCEPTOR_FD_ACQUIRE
|
|
|
|
// COMMON_INTERCEPTOR_FD_RELEASE
|
2013-10-11 22:13:11 +08:00
|
|
|
// COMMON_INTERCEPTOR_FD_ACCESS
|
2013-01-18 14:43:13 +08:00
|
|
|
// COMMON_INTERCEPTOR_SET_THREAD_NAME
|
2015-02-24 08:37:27 +08:00
|
|
|
// COMMON_INTERCEPTOR_ON_DLOPEN
|
2013-10-03 23:22:29 +08:00
|
|
|
// COMMON_INTERCEPTOR_ON_EXIT
|
2017-03-26 23:27:04 +08:00
|
|
|
// COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
|
|
|
|
// COMMON_INTERCEPTOR_MUTEX_POST_LOCK
|
2013-10-16 16:20:31 +08:00
|
|
|
// COMMON_INTERCEPTOR_MUTEX_UNLOCK
|
2013-11-16 00:58:12 +08:00
|
|
|
// COMMON_INTERCEPTOR_MUTEX_REPAIR
|
2013-10-29 18:30:39 +08:00
|
|
|
// COMMON_INTERCEPTOR_SET_PTHREAD_NAME
|
2013-11-28 17:09:42 +08:00
|
|
|
// COMMON_INTERCEPTOR_HANDLE_RECVMSG
|
2014-07-25 20:45:36 +08:00
|
|
|
// COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
|
2016-12-23 06:02:26 +08:00
|
|
|
// COMMON_INTERCEPTOR_MEMSET_IMPL
|
|
|
|
// COMMON_INTERCEPTOR_MEMMOVE_IMPL
|
|
|
|
// COMMON_INTERCEPTOR_MEMCPY_IMPL
|
2017-06-01 17:37:22 +08:00
|
|
|
// COMMON_INTERCEPTOR_COPY_STRING
|
|
|
|
// COMMON_INTERCEPTOR_STRNDUP_IMPL
|
2012-12-12 17:54:35 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2015-09-30 02:23:36 +08:00
|
|
|
|
2012-12-13 14:31:40 +08:00
|
|
|
#include "interception/interception.h"
|
2014-05-13 16:36:31 +08:00
|
|
|
#include "sanitizer_addrhashmap.h"
|
2017-07-06 08:50:57 +08:00
|
|
|
#include "sanitizer_errno.h"
|
2014-05-13 16:36:31 +08:00
|
|
|
#include "sanitizer_placement_new.h"
|
2012-12-13 16:50:16 +08:00
|
|
|
#include "sanitizer_platform_interceptors.h"
|
2017-09-27 00:12:56 +08:00
|
|
|
#include "sanitizer_symbolizer.h"
|
2014-01-29 17:29:16 +08:00
|
|
|
#include "sanitizer_tls_get_addr.h"
|
2012-12-13 13:27:08 +08:00
|
|
|
|
2013-01-18 19:17:23 +08:00
|
|
|
#include <stdarg.h>
|
|
|
|
|
2015-07-30 09:19:17 +08:00
|
|
|
#if SANITIZER_INTERCEPTOR_HOOKS
|
2017-02-01 11:31:09 +08:00
|
|
|
#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...) f(__VA_ARGS__);
|
|
|
|
#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...) \
|
|
|
|
SANITIZER_INTERFACE_WEAK_DEF(void, f, __VA_ARGS__) {}
|
2015-07-30 09:19:17 +08:00
|
|
|
#else
|
2015-07-30 10:32:51 +08:00
|
|
|
#define DECLARE_WEAK_INTERCEPTOR_HOOK(f, ...)
|
2015-08-06 02:56:42 +08:00
|
|
|
#define CALL_WEAK_INTERCEPTOR_HOOK(f, ...)
|
2015-07-30 10:32:51 +08:00
|
|
|
|
2015-07-30 09:19:17 +08:00
|
|
|
#endif // SANITIZER_INTERCEPTOR_HOOKS
|
|
|
|
|
2013-11-25 15:54:55 +08:00
|
|
|
#if SANITIZER_WINDOWS && !defined(va_copy)
|
2013-02-11 22:08:12 +08:00
|
|
|
#define va_copy(dst, src) ((dst) = (src))
|
|
|
|
#endif // _WIN32
|
|
|
|
|
2014-10-24 17:23:06 +08:00
|
|
|
#if SANITIZER_FREEBSD
|
|
|
|
#define pthread_setname_np pthread_set_name_np
|
2015-01-22 16:51:07 +08:00
|
|
|
#define inet_aton __inet_aton
|
|
|
|
#define inet_pton __inet_pton
|
2015-04-25 19:07:05 +08:00
|
|
|
#define iconv __bsd_iconv
|
2014-10-24 17:23:06 +08:00
|
|
|
#endif
|
|
|
|
|
2017-12-05 02:24:15 +08:00
|
|
|
#if SANITIZER_NETBSD
|
|
|
|
#define clock_getres __clock_getres50
|
|
|
|
#define clock_gettime __clock_gettime50
|
|
|
|
#define clock_settime __clock_settime50
|
|
|
|
#define ctime __ctime50
|
|
|
|
#define ctime_r __ctime_r50
|
|
|
|
#define getitimer __getitimer50
|
|
|
|
#define getpwent __getpwent50
|
|
|
|
#define getpwnam __getpwnam50
|
|
|
|
#define getpwnam_r __getpwnam_r50
|
|
|
|
#define getpwuid __getpwuid50
|
|
|
|
#define getpwuid_r __getpwuid_r50
|
|
|
|
#define getutent __getutent50
|
|
|
|
#define getutxent __getutxent50
|
|
|
|
#define getutxid __getutxid50
|
|
|
|
#define getutxline __getutxline50
|
|
|
|
#define glob __glob30
|
|
|
|
#define gmtime __gmtime50
|
|
|
|
#define gmtime_r __gmtime_r50
|
|
|
|
#define localtime_r __localtime_r50
|
|
|
|
#define mktime __mktime50
|
|
|
|
#define opendir __opendir30
|
|
|
|
#define readdir __readdir30
|
|
|
|
#define readdir_r __readdir_r30
|
|
|
|
#define scandir __scandir30
|
|
|
|
#define setitimer __setitimer50
|
|
|
|
#define setlocale __setlocale50
|
|
|
|
#define shmctl __shmctl50
|
|
|
|
#define sigemptyset __sigemptyset14
|
|
|
|
#define sigfillset __sigfillset14
|
|
|
|
#define sigpending __sigpending14
|
|
|
|
#define sigprocmask __sigprocmask14
|
|
|
|
#define sigtimedwait __sigtimedwait50
|
|
|
|
#define stat __stat50
|
|
|
|
#define time __time50
|
|
|
|
#define times __times13
|
|
|
|
#define wait3 __wait350
|
|
|
|
#define wait4 __wait450
|
|
|
|
#endif
|
|
|
|
|
2016-12-28 05:13:11 +08:00
|
|
|
// Platform-specific options.
|
|
|
|
#if SANITIZER_MAC
|
2016-12-28 05:30:20 +08:00
|
|
|
namespace __sanitizer {
|
2016-12-28 05:13:11 +08:00
|
|
|
bool PlatformHasDifferentMemcpyAndMemmove();
|
2016-12-28 05:30:20 +08:00
|
|
|
}
|
2016-12-28 05:13:11 +08:00
|
|
|
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE \
|
2016-12-28 05:30:20 +08:00
|
|
|
(__sanitizer::PlatformHasDifferentMemcpyAndMemmove())
|
2016-12-28 05:13:11 +08:00
|
|
|
#elif SANITIZER_WINDOWS64
|
|
|
|
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE false
|
|
|
|
#else
|
|
|
|
#define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE true
|
|
|
|
#endif // SANITIZER_MAC
|
|
|
|
|
2013-10-03 22:12:09 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_INITIALIZE_RANGE
|
2014-03-06 21:26:09 +08:00
|
|
|
#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(p, size) {}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef COMMON_INTERCEPTOR_UNPOISON_PARAM
|
|
|
|
#define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) {}
|
2013-10-03 22:12:09 +08:00
|
|
|
#endif
|
|
|
|
|
2013-10-11 22:13:11 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_FD_ACCESS
|
2013-10-29 18:30:39 +08:00
|
|
|
#define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) {}
|
2013-10-16 16:20:31 +08:00
|
|
|
#endif
|
|
|
|
|
2017-03-26 23:27:04 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_MUTEX_PRE_LOCK
|
|
|
|
#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) {}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef COMMON_INTERCEPTOR_MUTEX_POST_LOCK
|
|
|
|
#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) {}
|
2013-10-16 16:20:31 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef COMMON_INTERCEPTOR_MUTEX_UNLOCK
|
2013-10-29 18:30:39 +08:00
|
|
|
#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) {}
|
2013-10-11 22:13:11 +08:00
|
|
|
#endif
|
|
|
|
|
2013-11-16 00:58:12 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_MUTEX_REPAIR
|
|
|
|
#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) {}
|
|
|
|
#endif
|
|
|
|
|
2016-03-16 23:39:20 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_MUTEX_INVALID
|
|
|
|
#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) {}
|
|
|
|
#endif
|
|
|
|
|
2013-11-28 17:09:42 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_HANDLE_RECVMSG
|
|
|
|
#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg))
|
|
|
|
#endif
|
|
|
|
|
2014-04-25 21:26:21 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_FILE_OPEN
|
|
|
|
#define COMMON_INTERCEPTOR_FILE_OPEN(ctx, file, path) {}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef COMMON_INTERCEPTOR_FILE_CLOSE
|
|
|
|
#define COMMON_INTERCEPTOR_FILE_CLOSE(ctx, file) {}
|
|
|
|
#endif
|
|
|
|
|
2014-05-27 20:37:52 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_LIBRARY_LOADED
|
2015-01-30 20:43:52 +08:00
|
|
|
#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) {}
|
2014-05-27 20:37:52 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef COMMON_INTERCEPTOR_LIBRARY_UNLOADED
|
|
|
|
#define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() {}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef COMMON_INTERCEPTOR_ENTER_NOIGNORE
|
|
|
|
#define COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, ...) \
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __VA_ARGS__)
|
|
|
|
#endif
|
|
|
|
|
2014-07-25 20:45:36 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED
|
|
|
|
#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (0)
|
|
|
|
#endif
|
|
|
|
|
2017-04-21 16:21:56 +08:00
|
|
|
#define COMMON_INTERCEPTOR_READ_STRING(ctx, s, n) \
|
2017-04-22 03:39:46 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_RANGE((ctx), (s), \
|
|
|
|
common_flags()->strict_string_checks ? (REAL(strlen)(s)) + 1 : (n) )
|
2015-04-07 02:00:26 +08:00
|
|
|
|
2015-02-24 08:37:27 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_ON_DLOPEN
|
2017-03-09 18:47:38 +08:00
|
|
|
#define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \
|
|
|
|
CheckNoDeepBind(filename, flag);
|
2015-02-24 08:37:27 +08:00
|
|
|
#endif
|
|
|
|
|
2015-05-16 08:34:15 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_GET_TLS_RANGE
|
|
|
|
#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) *begin = *end = 0;
|
|
|
|
#endif
|
|
|
|
|
2015-08-28 02:51:18 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_ACQUIRE
|
|
|
|
#define COMMON_INTERCEPTOR_ACQUIRE(ctx, u) {}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef COMMON_INTERCEPTOR_RELEASE
|
|
|
|
#define COMMON_INTERCEPTOR_RELEASE(ctx, u) {}
|
|
|
|
#endif
|
|
|
|
|
2016-01-14 20:24:37 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_START
|
|
|
|
#define COMMON_INTERCEPTOR_USER_CALLBACK_START() {}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef COMMON_INTERCEPTOR_USER_CALLBACK_END
|
|
|
|
#define COMMON_INTERCEPTOR_USER_CALLBACK_END() {}
|
|
|
|
#endif
|
|
|
|
|
2016-04-28 05:24:21 +08:00
|
|
|
#ifdef SANITIZER_NLDBL_VERSION
|
|
|
|
#define COMMON_INTERCEPT_FUNCTION_LDBL(fn) \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_VER(fn, SANITIZER_NLDBL_VERSION)
|
|
|
|
#else
|
|
|
|
#define COMMON_INTERCEPT_FUNCTION_LDBL(fn) \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fn)
|
|
|
|
#endif
|
|
|
|
|
2016-12-23 06:02:26 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_MEMSET_IMPL
|
|
|
|
#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \
|
|
|
|
{ \
|
|
|
|
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \
|
|
|
|
return internal_memset(dst, v, size); \
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \
|
|
|
|
if (common_flags()->intercept_intrin) \
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
|
|
|
|
return REAL(memset)(dst, v, size); \
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef COMMON_INTERCEPTOR_MEMMOVE_IMPL
|
|
|
|
#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size) \
|
|
|
|
{ \
|
|
|
|
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \
|
|
|
|
return internal_memmove(dst, src, size); \
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, memmove, dst, src, size); \
|
|
|
|
if (common_flags()->intercept_intrin) { \
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \
|
|
|
|
} \
|
|
|
|
return REAL(memmove)(dst, src, size); \
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef COMMON_INTERCEPTOR_MEMCPY_IMPL
|
|
|
|
#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size) \
|
|
|
|
{ \
|
|
|
|
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) { \
|
|
|
|
return internal_memmove(dst, src, size); \
|
|
|
|
} \
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, memcpy, dst, src, size); \
|
|
|
|
if (common_flags()->intercept_intrin) { \
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, size); \
|
|
|
|
} \
|
|
|
|
return REAL(memcpy)(dst, src, size); \
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-06-01 17:37:22 +08:00
|
|
|
#ifndef COMMON_INTERCEPTOR_COPY_STRING
|
|
|
|
#define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) {}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef COMMON_INTERCEPTOR_STRNDUP_IMPL
|
2017-06-28 06:52:38 +08:00
|
|
|
#define COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size) \
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strndup, s, size); \
|
|
|
|
uptr copy_length = internal_strnlen(s, size); \
|
|
|
|
char *new_mem = (char *)WRAP(malloc)(copy_length + 1); \
|
|
|
|
if (common_flags()->intercept_strndup) { \
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, s, Min(size, copy_length + 1)); \
|
|
|
|
} \
|
|
|
|
COMMON_INTERCEPTOR_COPY_STRING(ctx, new_mem, s, copy_length); \
|
|
|
|
internal_memcpy(new_mem, s, copy_length); \
|
|
|
|
new_mem[copy_length] = '\0'; \
|
2017-06-01 17:37:22 +08:00
|
|
|
return new_mem;
|
|
|
|
#endif
|
|
|
|
|
2014-05-13 16:36:31 +08:00
|
|
|
struct FileMetadata {
|
|
|
|
// For open_memstream().
|
|
|
|
char **addr;
|
|
|
|
SIZE_T *size;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CommonInterceptorMetadata {
|
|
|
|
enum {
|
|
|
|
CIMT_INVALID = 0,
|
|
|
|
CIMT_FILE
|
|
|
|
} type;
|
|
|
|
union {
|
|
|
|
FileMetadata file;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef AddrHashMap<CommonInterceptorMetadata, 31051> MetadataHashMap;
|
|
|
|
|
|
|
|
static MetadataHashMap *interceptor_metadata_map;
|
|
|
|
|
2017-07-31 13:58:15 +08:00
|
|
|
#if SI_POSIX
|
2014-05-13 19:18:22 +08:00
|
|
|
UNUSED static void SetInterceptorMetadata(__sanitizer_FILE *addr,
|
|
|
|
const FileMetadata &file) {
|
2014-05-13 16:36:31 +08:00
|
|
|
MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr);
|
|
|
|
CHECK(h.created());
|
|
|
|
h->type = CommonInterceptorMetadata::CIMT_FILE;
|
|
|
|
h->file = file;
|
|
|
|
}
|
|
|
|
|
2014-05-13 19:18:22 +08:00
|
|
|
UNUSED static const FileMetadata *GetInterceptorMetadata(
|
|
|
|
__sanitizer_FILE *addr) {
|
2014-05-13 16:36:31 +08:00
|
|
|
MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr,
|
|
|
|
/* remove */ false,
|
|
|
|
/* create */ false);
|
2017-11-30 03:43:11 +08:00
|
|
|
if (addr && h.exists()) {
|
2014-05-13 16:36:31 +08:00
|
|
|
CHECK(!h.created());
|
|
|
|
CHECK(h->type == CommonInterceptorMetadata::CIMT_FILE);
|
|
|
|
return &h->file;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-13 19:18:22 +08:00
|
|
|
UNUSED static void DeleteInterceptorMetadata(void *addr) {
|
2014-05-13 16:36:31 +08:00
|
|
|
MetadataHashMap::Handle h(interceptor_metadata_map, (uptr)addr, true);
|
|
|
|
CHECK(h.exists());
|
|
|
|
}
|
2017-07-31 13:58:15 +08:00
|
|
|
#endif // SI_POSIX
|
2014-05-13 16:36:31 +08:00
|
|
|
|
2016-03-11 08:45:49 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STRLEN
|
|
|
|
INTERCEPTOR(SIZE_T, strlen, const char *s) {
|
2016-04-08 02:07:09 +08:00
|
|
|
// Sometimes strlen is called prior to InitializeCommonInterceptors,
|
|
|
|
// in which case the REAL(strlen) typically used in
|
|
|
|
// COMMON_INTERCEPTOR_ENTER will fail. We use internal_strlen here
|
|
|
|
// to handle that.
|
|
|
|
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
|
|
|
|
return internal_strlen(s);
|
2016-03-11 08:45:49 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strlen, s);
|
|
|
|
SIZE_T result = REAL(strlen)(s);
|
|
|
|
if (common_flags()->intercept_strlen)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s, result + 1);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
#define INIT_STRLEN COMMON_INTERCEPT_FUNCTION(strlen)
|
|
|
|
#else
|
|
|
|
#define INIT_STRLEN
|
|
|
|
#endif
|
|
|
|
|
2016-03-24 05:24:28 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STRNLEN
|
|
|
|
INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strnlen, s, maxlen);
|
|
|
|
SIZE_T length = REAL(strnlen)(s, maxlen);
|
|
|
|
if (common_flags()->intercept_strlen)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s, Min(length + 1, maxlen));
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
#define INIT_STRNLEN COMMON_INTERCEPT_FUNCTION(strnlen)
|
|
|
|
#else
|
|
|
|
#define INIT_STRNLEN
|
|
|
|
#endif
|
|
|
|
|
2017-06-01 17:37:22 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STRNDUP
|
|
|
|
INTERCEPTOR(char*, strndup, const char *s, uptr size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
|
|
|
|
}
|
|
|
|
#define INIT_STRNDUP COMMON_INTERCEPT_FUNCTION(strndup)
|
|
|
|
#else
|
|
|
|
#define INIT_STRNDUP
|
|
|
|
#endif // SANITIZER_INTERCEPT_STRNDUP
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT___STRNDUP
|
|
|
|
INTERCEPTOR(char*, __strndup, const char *s, uptr size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_STRNDUP_IMPL(ctx, s, size);
|
|
|
|
}
|
|
|
|
#define INIT___STRNDUP COMMON_INTERCEPT_FUNCTION(__strndup)
|
|
|
|
#else
|
|
|
|
#define INIT___STRNDUP
|
|
|
|
#endif // SANITIZER_INTERCEPT___STRNDUP
|
|
|
|
|
2013-12-02 21:43:26 +08:00
|
|
|
#if SANITIZER_INTERCEPT_TEXTDOMAIN
|
|
|
|
INTERCEPTOR(char*, textdomain, const char *domainname) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, textdomain, domainname);
|
2017-04-21 07:38:10 +08:00
|
|
|
if (domainname) COMMON_INTERCEPTOR_READ_STRING(ctx, domainname, 0);
|
2015-04-07 02:00:26 +08:00
|
|
|
char *domain = REAL(textdomain)(domainname);
|
2013-12-02 21:43:26 +08:00
|
|
|
if (domain) {
|
2014-03-06 21:26:09 +08:00
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(domain, REAL(strlen)(domain) + 1);
|
2013-12-02 21:43:26 +08:00
|
|
|
}
|
|
|
|
return domain;
|
|
|
|
}
|
|
|
|
#define INIT_TEXTDOMAIN COMMON_INTERCEPT_FUNCTION(textdomain)
|
|
|
|
#else
|
|
|
|
#define INIT_TEXTDOMAIN
|
|
|
|
#endif
|
|
|
|
|
2013-07-16 20:51:53 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STRCMP
|
|
|
|
static inline int CharCmpX(unsigned char c1, unsigned char c2) {
|
|
|
|
return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
|
|
|
|
}
|
|
|
|
|
2015-08-06 02:20:54 +08:00
|
|
|
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, uptr called_pc,
|
2016-01-12 08:43:42 +08:00
|
|
|
const char *s1, const char *s2, int result)
|
2015-08-06 02:20:54 +08:00
|
|
|
|
2013-07-16 20:51:53 +08:00
|
|
|
INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strcmp, s1, s2);
|
|
|
|
unsigned char c1, c2;
|
|
|
|
uptr i;
|
2013-11-11 19:28:30 +08:00
|
|
|
for (i = 0;; i++) {
|
2013-07-16 20:51:53 +08:00
|
|
|
c1 = (unsigned char)s1[i];
|
|
|
|
c2 = (unsigned char)s2[i];
|
|
|
|
if (c1 != c2 || c1 == '\0') break;
|
|
|
|
}
|
2015-04-07 02:00:26 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
|
2016-01-12 08:43:42 +08:00
|
|
|
int result = CharCmpX(c1, c2);
|
|
|
|
CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcmp, GET_CALLER_PC(), s1,
|
|
|
|
s2, result);
|
|
|
|
return result;
|
2013-07-16 20:51:53 +08:00
|
|
|
}
|
|
|
|
|
2015-07-30 10:32:51 +08:00
|
|
|
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, uptr called_pc,
|
2016-01-12 08:43:42 +08:00
|
|
|
const char *s1, const char *s2, uptr n,
|
|
|
|
int result)
|
2015-07-30 10:32:51 +08:00
|
|
|
|
2013-07-16 20:51:53 +08:00
|
|
|
INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
|
2014-07-25 20:45:36 +08:00
|
|
|
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
|
|
|
|
return internal_strncmp(s1, s2, size);
|
2013-07-16 20:51:53 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strncmp, s1, s2, size);
|
|
|
|
unsigned char c1 = 0, c2 = 0;
|
|
|
|
uptr i;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
|
|
c1 = (unsigned char)s1[i];
|
|
|
|
c2 = (unsigned char)s2[i];
|
|
|
|
if (c1 != c2 || c1 == '\0') break;
|
|
|
|
}
|
2016-11-12 12:32:31 +08:00
|
|
|
uptr i1 = i;
|
|
|
|
uptr i2 = i;
|
|
|
|
if (common_flags()->strict_string_checks) {
|
|
|
|
for (; i1 < size && s1[i1]; i1++) {}
|
|
|
|
for (; i2 < size && s2[i2]; i2++) {}
|
|
|
|
}
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
|
2016-01-12 08:43:42 +08:00
|
|
|
int result = CharCmpX(c1, c2);
|
|
|
|
CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncmp, GET_CALLER_PC(), s1,
|
|
|
|
s2, size, result);
|
|
|
|
return result;
|
2013-07-16 20:51:53 +08:00
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_STRCMP COMMON_INTERCEPT_FUNCTION(strcmp)
|
|
|
|
#define INIT_STRNCMP COMMON_INTERCEPT_FUNCTION(strncmp)
|
2013-07-16 20:51:53 +08:00
|
|
|
#else
|
|
|
|
#define INIT_STRCMP
|
|
|
|
#define INIT_STRNCMP
|
|
|
|
#endif
|
|
|
|
|
2013-03-26 20:40:23 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STRCASECMP
|
|
|
|
static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
|
|
|
|
int c1_low = ToLower(c1);
|
|
|
|
int c2_low = ToLower(c2);
|
|
|
|
return c1_low - c2_low;
|
|
|
|
}
|
|
|
|
|
2016-07-16 05:28:58 +08:00
|
|
|
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, uptr called_pc,
|
|
|
|
const char *s1, const char *s2, int result)
|
|
|
|
|
2013-03-26 20:40:23 +08:00
|
|
|
INTERCEPTOR(int, strcasecmp, const char *s1, const char *s2) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strcasecmp, s1, s2);
|
|
|
|
unsigned char c1 = 0, c2 = 0;
|
|
|
|
uptr i;
|
2013-11-11 19:28:30 +08:00
|
|
|
for (i = 0;; i++) {
|
2013-03-26 20:40:23 +08:00
|
|
|
c1 = (unsigned char)s1[i];
|
|
|
|
c2 = (unsigned char)s2[i];
|
2013-11-11 19:28:30 +08:00
|
|
|
if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
|
2013-03-26 20:40:23 +08:00
|
|
|
}
|
2015-04-07 02:00:26 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, s1, i + 1);
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, s2, i + 1);
|
2016-07-16 05:28:58 +08:00
|
|
|
int result = CharCaseCmp(c1, c2);
|
|
|
|
CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasecmp, GET_CALLER_PC(),
|
|
|
|
s1, s2, result);
|
|
|
|
return result;
|
2013-03-26 20:40:23 +08:00
|
|
|
}
|
|
|
|
|
2016-07-16 05:28:58 +08:00
|
|
|
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, uptr called_pc,
|
2016-11-12 12:32:31 +08:00
|
|
|
const char *s1, const char *s2, uptr size,
|
2016-07-16 05:28:58 +08:00
|
|
|
int result)
|
|
|
|
|
2016-11-12 12:32:31 +08:00
|
|
|
INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, SIZE_T size) {
|
2013-03-26 20:40:23 +08:00
|
|
|
void *ctx;
|
2016-11-12 12:32:31 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strncasecmp, s1, s2, size);
|
2013-03-26 20:40:23 +08:00
|
|
|
unsigned char c1 = 0, c2 = 0;
|
|
|
|
uptr i;
|
2016-11-12 12:32:31 +08:00
|
|
|
for (i = 0; i < size; i++) {
|
2013-03-26 20:40:23 +08:00
|
|
|
c1 = (unsigned char)s1[i];
|
|
|
|
c2 = (unsigned char)s2[i];
|
2013-11-11 19:28:30 +08:00
|
|
|
if (CharCaseCmp(c1, c2) != 0 || c1 == '\0') break;
|
2013-03-26 20:40:23 +08:00
|
|
|
}
|
2016-11-12 12:32:31 +08:00
|
|
|
uptr i1 = i;
|
|
|
|
uptr i2 = i;
|
|
|
|
if (common_flags()->strict_string_checks) {
|
|
|
|
for (; i1 < size && s1[i1]; i1++) {}
|
|
|
|
for (; i2 < size && s2[i2]; i2++) {}
|
|
|
|
}
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE((ctx), (s1), Min(i1 + 1, size));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE((ctx), (s2), Min(i2 + 1, size));
|
2016-07-16 05:28:58 +08:00
|
|
|
int result = CharCaseCmp(c1, c2);
|
|
|
|
CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strncasecmp, GET_CALLER_PC(),
|
2016-11-12 12:32:31 +08:00
|
|
|
s1, s2, size, result);
|
2016-07-16 05:28:58 +08:00
|
|
|
return result;
|
2013-03-26 20:40:23 +08:00
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_STRCASECMP COMMON_INTERCEPT_FUNCTION(strcasecmp)
|
|
|
|
#define INIT_STRNCASECMP COMMON_INTERCEPT_FUNCTION(strncasecmp)
|
2013-03-26 20:40:23 +08:00
|
|
|
#else
|
|
|
|
#define INIT_STRCASECMP
|
|
|
|
#define INIT_STRNCASECMP
|
|
|
|
#endif
|
|
|
|
|
2015-05-28 17:24:33 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STRSTR || SANITIZER_INTERCEPT_STRCASESTR
|
|
|
|
static inline void StrstrCheck(void *ctx, char *r, const char *s1,
|
|
|
|
const char *s2) {
|
|
|
|
uptr len1 = REAL(strlen)(s1);
|
|
|
|
uptr len2 = REAL(strlen)(s2);
|
2017-04-22 03:39:46 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r ? r - s1 + len2 : len1 + 1);
|
2015-05-28 17:24:33 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2 + 1);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_STRSTR
|
2016-07-16 05:28:58 +08:00
|
|
|
|
|
|
|
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, uptr called_pc,
|
2016-07-19 23:30:22 +08:00
|
|
|
const char *s1, const char *s2, char *result)
|
2016-07-16 05:28:58 +08:00
|
|
|
|
2015-05-28 17:24:33 +08:00
|
|
|
INTERCEPTOR(char*, strstr, const char *s1, const char *s2) {
|
|
|
|
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
|
|
|
|
return internal_strstr(s1, s2);
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strstr, s1, s2);
|
|
|
|
char *r = REAL(strstr)(s1, s2);
|
|
|
|
if (common_flags()->intercept_strstr)
|
|
|
|
StrstrCheck(ctx, r, s1, s2);
|
2016-07-16 05:28:58 +08:00
|
|
|
CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strstr, GET_CALLER_PC(), s1,
|
|
|
|
s2, r);
|
2015-05-28 17:24:33 +08:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_STRSTR COMMON_INTERCEPT_FUNCTION(strstr);
|
|
|
|
#else
|
|
|
|
#define INIT_STRSTR
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_STRCASESTR
|
2016-07-16 05:28:58 +08:00
|
|
|
|
|
|
|
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, uptr called_pc,
|
2016-07-19 23:30:22 +08:00
|
|
|
const char *s1, const char *s2, char *result)
|
2016-07-16 05:28:58 +08:00
|
|
|
|
2015-05-28 17:24:33 +08:00
|
|
|
INTERCEPTOR(char*, strcasestr, const char *s1, const char *s2) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strcasestr, s1, s2);
|
|
|
|
char *r = REAL(strcasestr)(s1, s2);
|
|
|
|
if (common_flags()->intercept_strstr)
|
|
|
|
StrstrCheck(ctx, r, s1, s2);
|
2016-07-16 05:28:58 +08:00
|
|
|
CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_strcasestr, GET_CALLER_PC(),
|
|
|
|
s1, s2, r);
|
2015-05-28 17:24:33 +08:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_STRCASESTR COMMON_INTERCEPT_FUNCTION(strcasestr);
|
|
|
|
#else
|
|
|
|
#define INIT_STRCASESTR
|
|
|
|
#endif
|
|
|
|
|
2017-03-24 05:39:52 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STRTOK
|
|
|
|
|
|
|
|
INTERCEPTOR(char*, strtok, char *str, const char *delimiters) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strtok, str, delimiters);
|
|
|
|
if (!common_flags()->intercept_strtok) {
|
|
|
|
return REAL(strtok)(str, delimiters);
|
|
|
|
}
|
|
|
|
if (common_flags()->strict_string_checks) {
|
|
|
|
// If strict_string_checks is enabled, we check the whole first argument
|
|
|
|
// string on the first call (strtok saves this string in a static buffer
|
|
|
|
// for subsequent calls). We do not need to check strtok's result.
|
|
|
|
// As the delimiters can change, we check them every call.
|
|
|
|
if (str != nullptr) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
|
|
|
|
}
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters,
|
|
|
|
REAL(strlen)(delimiters) + 1);
|
|
|
|
return REAL(strtok)(str, delimiters);
|
|
|
|
} else {
|
|
|
|
// However, when strict_string_checks is disabled we cannot check the
|
|
|
|
// whole string on the first call. Instead, we check the result string
|
|
|
|
// which is guaranteed to be a NULL-terminated substring of the first
|
|
|
|
// argument. We also conservatively check one character of str and the
|
|
|
|
// delimiters.
|
|
|
|
if (str != nullptr) {
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, str, 1);
|
|
|
|
}
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, delimiters, 1);
|
|
|
|
char *result = REAL(strtok)(str, delimiters);
|
|
|
|
if (result != nullptr) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, result, REAL(strlen)(result) + 1);
|
|
|
|
} else if (str != nullptr) {
|
|
|
|
// No delimiter were found, it's safe to assume that the entire str was
|
|
|
|
// scanned.
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, str, REAL(strlen)(str) + 1);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_STRTOK COMMON_INTERCEPT_FUNCTION(strtok)
|
|
|
|
#else
|
|
|
|
#define INIT_STRTOK
|
|
|
|
#endif
|
|
|
|
|
2016-07-16 05:28:58 +08:00
|
|
|
#if SANITIZER_INTERCEPT_MEMMEM
|
|
|
|
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, uptr called_pc,
|
|
|
|
const void *s1, SIZE_T len1, const void *s2,
|
2016-07-19 23:30:22 +08:00
|
|
|
SIZE_T len2, void *result)
|
2016-07-16 05:28:58 +08:00
|
|
|
|
|
|
|
INTERCEPTOR(void*, memmem, const void *s1, SIZE_T len1, const void *s2,
|
|
|
|
SIZE_T len2) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, memmem, s1, len1, s2, len2);
|
|
|
|
void *r = REAL(memmem)(s1, len1, s2, len2);
|
|
|
|
if (common_flags()->intercept_memmem) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, len1);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, len2);
|
|
|
|
}
|
|
|
|
CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memmem, GET_CALLER_PC(),
|
|
|
|
s1, len1, s2, len2, r);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_MEMMEM COMMON_INTERCEPT_FUNCTION(memmem);
|
|
|
|
#else
|
|
|
|
#define INIT_MEMMEM
|
|
|
|
#endif // SANITIZER_INTERCEPT_MEMMEM
|
|
|
|
|
2016-03-22 05:36:17 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STRCHR
|
|
|
|
INTERCEPTOR(char*, strchr, const char *s, int c) {
|
|
|
|
void *ctx;
|
2016-04-28 05:20:46 +08:00
|
|
|
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
|
|
|
|
return internal_strchr(s, c);
|
2016-03-22 05:36:17 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strchr, s, c);
|
|
|
|
char *result = REAL(strchr)(s, c);
|
2017-04-22 03:39:46 +08:00
|
|
|
if (common_flags()->intercept_strchr) {
|
|
|
|
// Keep strlen as macro argument, as macro may ignore it.
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, s,
|
|
|
|
(result ? result - s : REAL(strlen)(s)) + 1);
|
|
|
|
}
|
2016-03-22 05:36:17 +08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
#define INIT_STRCHR COMMON_INTERCEPT_FUNCTION(strchr)
|
|
|
|
#else
|
|
|
|
#define INIT_STRCHR
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_STRCHRNUL
|
|
|
|
INTERCEPTOR(char*, strchrnul, const char *s, int c) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strchrnul, s, c);
|
|
|
|
char *result = REAL(strchrnul)(s, c);
|
|
|
|
uptr len = result - s + 1;
|
|
|
|
if (common_flags()->intercept_strchr)
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, s, len);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
#define INIT_STRCHRNUL COMMON_INTERCEPT_FUNCTION(strchrnul)
|
|
|
|
#else
|
|
|
|
#define INIT_STRCHRNUL
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_STRRCHR
|
|
|
|
INTERCEPTOR(char*, strrchr, const char *s, int c) {
|
|
|
|
void *ctx;
|
2016-04-28 05:20:46 +08:00
|
|
|
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
|
|
|
|
return internal_strrchr(s, c);
|
2016-03-22 05:36:17 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strrchr, s, c);
|
|
|
|
if (common_flags()->intercept_strchr)
|
2017-04-22 03:39:46 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
|
2016-03-22 05:36:17 +08:00
|
|
|
return REAL(strrchr)(s, c);
|
|
|
|
}
|
|
|
|
#define INIT_STRRCHR COMMON_INTERCEPT_FUNCTION(strrchr)
|
|
|
|
#else
|
|
|
|
#define INIT_STRRCHR
|
|
|
|
#endif
|
|
|
|
|
2015-05-28 17:24:33 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STRSPN
|
|
|
|
INTERCEPTOR(SIZE_T, strspn, const char *s1, const char *s2) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strspn, s1, s2);
|
|
|
|
SIZE_T r = REAL(strspn)(s1, s2);
|
|
|
|
if (common_flags()->intercept_strspn) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(SIZE_T, strcspn, const char *s1, const char *s2) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strcspn, s1, s2);
|
|
|
|
SIZE_T r = REAL(strcspn)(s1, s2);
|
|
|
|
if (common_flags()->intercept_strspn) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, s1, r + 1);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_STRSPN \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(strspn); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(strcspn);
|
|
|
|
#else
|
|
|
|
#define INIT_STRSPN
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_STRPBRK
|
|
|
|
INTERCEPTOR(char *, strpbrk, const char *s1, const char *s2) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strpbrk, s1, s2);
|
|
|
|
char *r = REAL(strpbrk)(s1, s2);
|
|
|
|
if (common_flags()->intercept_strpbrk) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, REAL(strlen)(s2) + 1);
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, s1,
|
|
|
|
r ? r - s1 + 1 : REAL(strlen)(s1) + 1);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_STRPBRK COMMON_INTERCEPT_FUNCTION(strpbrk);
|
|
|
|
#else
|
|
|
|
#define INIT_STRPBRK
|
|
|
|
#endif
|
|
|
|
|
[sanitizer] Add memset, memmove, and memcpy to the common interceptors
Summary:
Currently, sanitizer_common_interceptors.inc has an implicit, undocumented
assumption that the sanitizer including it has previously declared
interceptors for memset and memmove. Since the memset, memmove, and memcpy
routines require interception by many sanitizers, we add them to the
set of common interceptions, both to address the undocumented assumption
and to speed future tool development. They are intercepted under a new
flag intercept_intrin.
The tsan interceptors are removed in favor of the new common versions. The
asan and msan interceptors for these are more complex (they incur extra
interception steps and their function bodies are exposed to the compiler)
so they opt out of the common versions and keep their own.
Reviewers: vitalybuka
Subscribers: zhaoqin, llvm-commits, kcc
Differential Revision: http://reviews.llvm.org/D18465
llvm-svn: 264451
2016-03-26 03:33:45 +08:00
|
|
|
#if SANITIZER_INTERCEPT_MEMSET
|
2016-12-23 06:02:26 +08:00
|
|
|
INTERCEPTOR(void *, memset, void *dst, int v, uptr size) {
|
[sanitizer] Add memset, memmove, and memcpy to the common interceptors
Summary:
Currently, sanitizer_common_interceptors.inc has an implicit, undocumented
assumption that the sanitizer including it has previously declared
interceptors for memset and memmove. Since the memset, memmove, and memcpy
routines require interception by many sanitizers, we add them to the
set of common interceptions, both to address the undocumented assumption
and to speed future tool development. They are intercepted under a new
flag intercept_intrin.
The tsan interceptors are removed in favor of the new common versions. The
asan and msan interceptors for these are more complex (they incur extra
interception steps and their function bodies are exposed to the compiler)
so they opt out of the common versions and keep their own.
Reviewers: vitalybuka
Subscribers: zhaoqin, llvm-commits, kcc
Differential Revision: http://reviews.llvm.org/D18465
llvm-svn: 264451
2016-03-26 03:33:45 +08:00
|
|
|
void *ctx;
|
2016-12-23 06:02:26 +08:00
|
|
|
COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size);
|
[sanitizer] Add memset, memmove, and memcpy to the common interceptors
Summary:
Currently, sanitizer_common_interceptors.inc has an implicit, undocumented
assumption that the sanitizer including it has previously declared
interceptors for memset and memmove. Since the memset, memmove, and memcpy
routines require interception by many sanitizers, we add them to the
set of common interceptions, both to address the undocumented assumption
and to speed future tool development. They are intercepted under a new
flag intercept_intrin.
The tsan interceptors are removed in favor of the new common versions. The
asan and msan interceptors for these are more complex (they incur extra
interception steps and their function bodies are exposed to the compiler)
so they opt out of the common versions and keep their own.
Reviewers: vitalybuka
Subscribers: zhaoqin, llvm-commits, kcc
Differential Revision: http://reviews.llvm.org/D18465
llvm-svn: 264451
2016-03-26 03:33:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_MEMSET COMMON_INTERCEPT_FUNCTION(memset)
|
|
|
|
#else
|
|
|
|
#define INIT_MEMSET
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_MEMMOVE
|
2016-12-23 06:02:26 +08:00
|
|
|
INTERCEPTOR(void *, memmove, void *dst, const void *src, uptr size) {
|
[sanitizer] Add memset, memmove, and memcpy to the common interceptors
Summary:
Currently, sanitizer_common_interceptors.inc has an implicit, undocumented
assumption that the sanitizer including it has previously declared
interceptors for memset and memmove. Since the memset, memmove, and memcpy
routines require interception by many sanitizers, we add them to the
set of common interceptions, both to address the undocumented assumption
and to speed future tool development. They are intercepted under a new
flag intercept_intrin.
The tsan interceptors are removed in favor of the new common versions. The
asan and msan interceptors for these are more complex (they incur extra
interception steps and their function bodies are exposed to the compiler)
so they opt out of the common versions and keep their own.
Reviewers: vitalybuka
Subscribers: zhaoqin, llvm-commits, kcc
Differential Revision: http://reviews.llvm.org/D18465
llvm-svn: 264451
2016-03-26 03:33:45 +08:00
|
|
|
void *ctx;
|
2016-12-23 06:02:26 +08:00
|
|
|
COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
|
[sanitizer] Add memset, memmove, and memcpy to the common interceptors
Summary:
Currently, sanitizer_common_interceptors.inc has an implicit, undocumented
assumption that the sanitizer including it has previously declared
interceptors for memset and memmove. Since the memset, memmove, and memcpy
routines require interception by many sanitizers, we add them to the
set of common interceptions, both to address the undocumented assumption
and to speed future tool development. They are intercepted under a new
flag intercept_intrin.
The tsan interceptors are removed in favor of the new common versions. The
asan and msan interceptors for these are more complex (they incur extra
interception steps and their function bodies are exposed to the compiler)
so they opt out of the common versions and keep their own.
Reviewers: vitalybuka
Subscribers: zhaoqin, llvm-commits, kcc
Differential Revision: http://reviews.llvm.org/D18465
llvm-svn: 264451
2016-03-26 03:33:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_MEMMOVE COMMON_INTERCEPT_FUNCTION(memmove)
|
|
|
|
#else
|
|
|
|
#define INIT_MEMMOVE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_MEMCPY
|
2016-12-23 06:02:26 +08:00
|
|
|
INTERCEPTOR(void *, memcpy, void *dst, const void *src, uptr size) {
|
2016-12-28 05:13:11 +08:00
|
|
|
// On OS X, calling internal_memcpy here will cause memory corruptions,
|
|
|
|
// because memcpy and memmove are actually aliases of the same
|
|
|
|
// implementation. We need to use internal_memmove here.
|
|
|
|
// N.B.: If we switch this to internal_ we'll have to use internal_memmove
|
|
|
|
// due to memcpy being an alias of memmove on OS X.
|
[sanitizer] Add memset, memmove, and memcpy to the common interceptors
Summary:
Currently, sanitizer_common_interceptors.inc has an implicit, undocumented
assumption that the sanitizer including it has previously declared
interceptors for memset and memmove. Since the memset, memmove, and memcpy
routines require interception by many sanitizers, we add them to the
set of common interceptions, both to address the undocumented assumption
and to speed future tool development. They are intercepted under a new
flag intercept_intrin.
The tsan interceptors are removed in favor of the new common versions. The
asan and msan interceptors for these are more complex (they incur extra
interception steps and their function bodies are exposed to the compiler)
so they opt out of the common versions and keep their own.
Reviewers: vitalybuka
Subscribers: zhaoqin, llvm-commits, kcc
Differential Revision: http://reviews.llvm.org/D18465
llvm-svn: 264451
2016-03-26 03:33:45 +08:00
|
|
|
void *ctx;
|
2016-12-28 05:13:11 +08:00
|
|
|
if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
|
|
|
|
COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, dst, src, size);
|
|
|
|
} else {
|
|
|
|
COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, dst, src, size);
|
|
|
|
}
|
[sanitizer] Add memset, memmove, and memcpy to the common interceptors
Summary:
Currently, sanitizer_common_interceptors.inc has an implicit, undocumented
assumption that the sanitizer including it has previously declared
interceptors for memset and memmove. Since the memset, memmove, and memcpy
routines require interception by many sanitizers, we add them to the
set of common interceptions, both to address the undocumented assumption
and to speed future tool development. They are intercepted under a new
flag intercept_intrin.
The tsan interceptors are removed in favor of the new common versions. The
asan and msan interceptors for these are more complex (they incur extra
interception steps and their function bodies are exposed to the compiler)
so they opt out of the common versions and keep their own.
Reviewers: vitalybuka
Subscribers: zhaoqin, llvm-commits, kcc
Differential Revision: http://reviews.llvm.org/D18465
llvm-svn: 264451
2016-03-26 03:33:45 +08:00
|
|
|
}
|
|
|
|
|
2016-12-28 05:13:11 +08:00
|
|
|
#define INIT_MEMCPY \
|
|
|
|
do { \
|
|
|
|
if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(memcpy); \
|
|
|
|
} else { \
|
|
|
|
ASSIGN_REAL(memcpy, memmove); \
|
|
|
|
} \
|
|
|
|
CHECK(REAL(memcpy)); \
|
|
|
|
} while (false)
|
|
|
|
|
[sanitizer] Add memset, memmove, and memcpy to the common interceptors
Summary:
Currently, sanitizer_common_interceptors.inc has an implicit, undocumented
assumption that the sanitizer including it has previously declared
interceptors for memset and memmove. Since the memset, memmove, and memcpy
routines require interception by many sanitizers, we add them to the
set of common interceptions, both to address the undocumented assumption
and to speed future tool development. They are intercepted under a new
flag intercept_intrin.
The tsan interceptors are removed in favor of the new common versions. The
asan and msan interceptors for these are more complex (they incur extra
interception steps and their function bodies are exposed to the compiler)
so they opt out of the common versions and keep their own.
Reviewers: vitalybuka
Subscribers: zhaoqin, llvm-commits, kcc
Differential Revision: http://reviews.llvm.org/D18465
llvm-svn: 264451
2016-03-26 03:33:45 +08:00
|
|
|
#else
|
|
|
|
#define INIT_MEMCPY
|
|
|
|
#endif
|
|
|
|
|
2015-07-30 07:53:08 +08:00
|
|
|
#if SANITIZER_INTERCEPT_MEMCMP
|
2015-07-30 09:19:17 +08:00
|
|
|
|
2015-07-30 10:32:51 +08:00
|
|
|
DECLARE_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, uptr called_pc,
|
2016-01-12 08:43:42 +08:00
|
|
|
const void *s1, const void *s2, uptr n,
|
|
|
|
int result)
|
2015-07-30 09:19:17 +08:00
|
|
|
|
2015-07-30 07:53:08 +08:00
|
|
|
INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
|
|
|
|
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
|
|
|
|
return internal_memcmp(a1, a2, size);
|
2015-12-08 22:48:21 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, memcmp, a1, a2, size);
|
2015-07-30 07:53:08 +08:00
|
|
|
if (common_flags()->intercept_memcmp) {
|
|
|
|
if (common_flags()->strict_memcmp) {
|
|
|
|
// Check the entire regions even if the first bytes of the buffers are
|
|
|
|
// different.
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, a1, size);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, a2, size);
|
|
|
|
// Fallthrough to REAL(memcmp) below.
|
|
|
|
} else {
|
|
|
|
unsigned char c1 = 0, c2 = 0;
|
|
|
|
const unsigned char *s1 = (const unsigned char*)a1;
|
|
|
|
const unsigned char *s2 = (const unsigned char*)a2;
|
|
|
|
uptr i;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
|
|
c1 = s1[i];
|
|
|
|
c2 = s2[i];
|
|
|
|
if (c1 != c2) break;
|
|
|
|
}
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s1, Min(i + 1, size));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s2, Min(i + 1, size));
|
2016-01-12 08:43:42 +08:00
|
|
|
int r = CharCmpX(c1, c2);
|
|
|
|
CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(),
|
|
|
|
a1, a2, size, r);
|
|
|
|
return r;
|
2015-07-30 07:53:08 +08:00
|
|
|
}
|
|
|
|
}
|
2016-01-12 08:43:42 +08:00
|
|
|
int result = REAL(memcmp(a1, a2, size));
|
|
|
|
CALL_WEAK_INTERCEPTOR_HOOK(__sanitizer_weak_hook_memcmp, GET_CALLER_PC(), a1,
|
|
|
|
a2, size, result);
|
|
|
|
return result;
|
2015-07-30 07:53:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_MEMCMP COMMON_INTERCEPT_FUNCTION(memcmp)
|
|
|
|
#else
|
|
|
|
#define INIT_MEMCMP
|
|
|
|
#endif
|
|
|
|
|
2014-03-05 21:25:32 +08:00
|
|
|
#if SANITIZER_INTERCEPT_MEMCHR
|
|
|
|
INTERCEPTOR(void*, memchr, const void *s, int c, SIZE_T n) {
|
2015-11-04 00:19:37 +08:00
|
|
|
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
|
|
|
|
return internal_memchr(s, c, n);
|
2014-03-05 21:25:32 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, memchr, s, c, n);
|
[compiler-rt] Fix warnings in interception code
Summary:
This patch is re-introducing the code to fix the
dynamic hooking on windows and to fix a compiler
warning on Apple.
Related patches:
* https://reviews.llvm.org/D22641
* https://reviews.llvm.org/D22610
* https://reviews.llvm.org/rL276311
* https://reviews.llvm.org/rL276490
Both architecture are using different techniques to
hook on library functions (memchr, strcpy,...).
On Apple, the function is not dynamically hooked and
the symbol always points to a valid function
(i.e. can't be null). The REAL macro returns the
symbol.
On windows, the function is dynamically patch and the
REAL(...) function may or may not be null. It depend
on whether or not the function was hooked correctly.
Also, on windows memcpy and memmove are the same.
```
#if !defined(__APPLE__)
[...]
# define REAL(x) __interception::PTR_TO_REAL(x)
# define ASSIGN_REAL(dst, src) REAL(dst) = REAL(src)
[...]
#else // __APPLE__
[...]
# define REAL(x) x
# define ASSIGN_REAL(x, y)
[...]
#endif // __APPLE__
Reviewers: rnk
Subscribers: kcc, hans, kubabrecka, llvm-commits, bruno, chrisha
Differential Revision: https://reviews.llvm.org/D22758
llvm-svn: 276885
2016-07-28 00:16:54 +08:00
|
|
|
#if SANITIZER_WINDOWS
|
2016-07-22 03:49:11 +08:00
|
|
|
void *res;
|
2016-07-24 09:27:07 +08:00
|
|
|
if (REAL(memchr)) {
|
2016-07-22 03:49:11 +08:00
|
|
|
res = REAL(memchr)(s, c, n);
|
|
|
|
} else {
|
|
|
|
res = internal_memchr(s, c, n);
|
|
|
|
}
|
[compiler-rt] Fix warnings in interception code
Summary:
This patch is re-introducing the code to fix the
dynamic hooking on windows and to fix a compiler
warning on Apple.
Related patches:
* https://reviews.llvm.org/D22641
* https://reviews.llvm.org/D22610
* https://reviews.llvm.org/rL276311
* https://reviews.llvm.org/rL276490
Both architecture are using different techniques to
hook on library functions (memchr, strcpy,...).
On Apple, the function is not dynamically hooked and
the symbol always points to a valid function
(i.e. can't be null). The REAL macro returns the
symbol.
On windows, the function is dynamically patch and the
REAL(...) function may or may not be null. It depend
on whether or not the function was hooked correctly.
Also, on windows memcpy and memmove are the same.
```
#if !defined(__APPLE__)
[...]
# define REAL(x) __interception::PTR_TO_REAL(x)
# define ASSIGN_REAL(dst, src) REAL(dst) = REAL(src)
[...]
#else // __APPLE__
[...]
# define REAL(x) x
# define ASSIGN_REAL(x, y)
[...]
#endif // __APPLE__
Reviewers: rnk
Subscribers: kcc, hans, kubabrecka, llvm-commits, bruno, chrisha
Differential Revision: https://reviews.llvm.org/D22758
llvm-svn: 276885
2016-07-28 00:16:54 +08:00
|
|
|
#else
|
|
|
|
void *res = REAL(memchr)(s, c, n);
|
|
|
|
#endif
|
2014-11-14 06:40:59 +08:00
|
|
|
uptr len = res ? (char *)res - (const char *)s + 1 : n;
|
2014-03-05 21:25:32 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s, len);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_MEMCHR COMMON_INTERCEPT_FUNCTION(memchr)
|
|
|
|
#else
|
|
|
|
#define INIT_MEMCHR
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_MEMRCHR
|
|
|
|
INTERCEPTOR(void*, memrchr, const void *s, int c, SIZE_T n) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, memrchr, s, c, n);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s, n);
|
|
|
|
return REAL(memrchr)(s, c, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_MEMRCHR COMMON_INTERCEPT_FUNCTION(memrchr)
|
|
|
|
#else
|
|
|
|
#define INIT_MEMRCHR
|
|
|
|
#endif
|
|
|
|
|
2013-03-14 19:34:39 +08:00
|
|
|
#if SANITIZER_INTERCEPT_FREXP
|
|
|
|
INTERCEPTOR(double, frexp, double x, int *exp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, frexp, x, exp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// Assuming frexp() always writes to |exp|.
|
2013-03-14 19:34:39 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
|
2014-06-18 17:27:40 +08:00
|
|
|
double res = REAL(frexp)(x, exp);
|
2013-03-14 19:34:39 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_FREXP COMMON_INTERCEPT_FUNCTION(frexp);
|
2013-03-15 22:02:21 +08:00
|
|
|
#else
|
|
|
|
#define INIT_FREXP
|
2013-11-11 19:28:30 +08:00
|
|
|
#endif // SANITIZER_INTERCEPT_FREXP
|
2013-03-15 22:02:21 +08:00
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_FREXPF_FREXPL
|
2013-03-14 19:34:39 +08:00
|
|
|
INTERCEPTOR(float, frexpf, float x, int *exp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, frexpf, x, exp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-03-14 19:34:39 +08:00
|
|
|
float res = REAL(frexpf)(x, exp);
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(long double, frexpl, long double x, int *exp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, frexpl, x, exp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-03-14 19:34:39 +08:00
|
|
|
long double res = REAL(frexpl)(x, exp);
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, exp, sizeof(*exp));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_FREXPF_FREXPL \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(frexpf); \
|
2016-04-28 05:24:21 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(frexpl)
|
2013-03-14 19:34:39 +08:00
|
|
|
#else
|
2013-03-15 22:02:21 +08:00
|
|
|
#define INIT_FREXPF_FREXPL
|
2013-11-11 19:28:30 +08:00
|
|
|
#endif // SANITIZER_INTERCEPT_FREXPF_FREXPL
|
2013-03-14 19:34:39 +08:00
|
|
|
|
2017-07-31 13:58:15 +08:00
|
|
|
#if SI_POSIX
|
2013-06-24 18:43:23 +08:00
|
|
|
static void write_iovec(void *ctx, struct __sanitizer_iovec *iovec,
|
|
|
|
SIZE_T iovlen, SIZE_T maxlen) {
|
|
|
|
for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
|
|
|
|
SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec[i].iov_base, sz);
|
|
|
|
maxlen -= sz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void read_iovec(void *ctx, struct __sanitizer_iovec *iovec,
|
|
|
|
SIZE_T iovlen, SIZE_T maxlen) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec) * iovlen);
|
|
|
|
for (SIZE_T i = 0; i < iovlen && maxlen; ++i) {
|
|
|
|
SSIZE_T sz = Min(iovec[i].iov_len, maxlen);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec[i].iov_base, sz);
|
|
|
|
maxlen -= sz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-12-13 16:36:13 +08:00
|
|
|
#if SANITIZER_INTERCEPT_READ
|
2012-12-13 14:31:40 +08:00
|
|
|
INTERCEPTOR(SSIZE_T, read, int fd, void *ptr, SIZE_T count) {
|
2013-02-11 23:22:34 +08:00
|
|
|
void *ctx;
|
2013-01-18 19:17:23 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, read, fd, ptr, count);
|
2013-10-11 22:13:11 +08:00
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2012-12-13 14:31:40 +08:00
|
|
|
SSIZE_T res = REAL(read)(fd, ptr, count);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
|
|
|
|
if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
2012-12-12 17:54:35 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_READ COMMON_INTERCEPT_FUNCTION(read)
|
2013-01-18 14:43:13 +08:00
|
|
|
#else
|
2013-02-11 23:22:34 +08:00
|
|
|
#define INIT_READ
|
2012-12-13 16:36:13 +08:00
|
|
|
#endif
|
2012-12-12 17:54:35 +08:00
|
|
|
|
2017-03-30 15:25:33 +08:00
|
|
|
#if SANITIZER_INTERCEPT_FREAD
|
|
|
|
INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
|
|
|
|
// libc file streams can call user-supplied functions, see fopencookie.
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fread, ptr, size, nmemb, file);
|
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
|
|
|
SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
|
|
|
|
if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res * size);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_FREAD COMMON_INTERCEPT_FUNCTION(fread)
|
|
|
|
#else
|
|
|
|
#define INIT_FREAD
|
|
|
|
#endif
|
|
|
|
|
2012-12-13 16:10:23 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PREAD
|
2012-12-13 14:31:40 +08:00
|
|
|
INTERCEPTOR(SSIZE_T, pread, int fd, void *ptr, SIZE_T count, OFF_T offset) {
|
2013-02-11 23:22:34 +08:00
|
|
|
void *ctx;
|
2013-01-18 19:17:23 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pread, fd, ptr, count, offset);
|
2013-10-11 22:13:11 +08:00
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2012-12-13 14:31:40 +08:00
|
|
|
SSIZE_T res = REAL(pread)(fd, ptr, count, offset);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
|
|
|
|
if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
2012-12-12 17:54:35 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PREAD COMMON_INTERCEPT_FUNCTION(pread)
|
2013-01-18 14:43:13 +08:00
|
|
|
#else
|
2013-02-11 23:22:34 +08:00
|
|
|
#define INIT_PREAD
|
2012-12-13 16:10:23 +08:00
|
|
|
#endif
|
2012-12-12 17:54:35 +08:00
|
|
|
|
2012-12-13 13:27:08 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PREAD64
|
2012-12-13 14:31:40 +08:00
|
|
|
INTERCEPTOR(SSIZE_T, pread64, int fd, void *ptr, SIZE_T count, OFF64_T offset) {
|
2013-02-11 23:22:34 +08:00
|
|
|
void *ctx;
|
2013-01-18 19:17:23 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pread64, fd, ptr, count, offset);
|
2013-10-11 22:13:11 +08:00
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2012-12-13 14:31:40 +08:00
|
|
|
SSIZE_T res = REAL(pread64)(fd, ptr, count, offset);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (res > 0) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, res);
|
|
|
|
if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
2012-12-12 17:54:35 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PREAD64 COMMON_INTERCEPT_FUNCTION(pread64)
|
2013-01-18 14:43:13 +08:00
|
|
|
#else
|
2013-02-11 23:22:34 +08:00
|
|
|
#define INIT_PREAD64
|
2012-12-12 19:52:26 +08:00
|
|
|
#endif
|
2012-12-12 17:54:35 +08:00
|
|
|
|
2013-06-24 18:43:23 +08:00
|
|
|
#if SANITIZER_INTERCEPT_READV
|
|
|
|
INTERCEPTOR_WITH_SUFFIX(SSIZE_T, readv, int fd, __sanitizer_iovec *iov,
|
|
|
|
int iovcnt) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, readv, fd, iov, iovcnt);
|
2013-10-11 22:13:11 +08:00
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
2013-06-24 18:43:23 +08:00
|
|
|
SSIZE_T res = REAL(readv)(fd, iov, iovcnt);
|
|
|
|
if (res > 0) write_iovec(ctx, iov, iovcnt, res);
|
|
|
|
if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_READV COMMON_INTERCEPT_FUNCTION(readv)
|
2013-06-24 18:43:23 +08:00
|
|
|
#else
|
|
|
|
#define INIT_READV
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PREADV
|
|
|
|
INTERCEPTOR(SSIZE_T, preadv, int fd, __sanitizer_iovec *iov, int iovcnt,
|
|
|
|
OFF_T offset) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, preadv, fd, iov, iovcnt, offset);
|
2013-10-11 22:13:11 +08:00
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
2013-06-24 18:43:23 +08:00
|
|
|
SSIZE_T res = REAL(preadv)(fd, iov, iovcnt, offset);
|
|
|
|
if (res > 0) write_iovec(ctx, iov, iovcnt, res);
|
|
|
|
if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PREADV COMMON_INTERCEPT_FUNCTION(preadv)
|
2013-06-24 18:43:23 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PREADV
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PREADV64
|
|
|
|
INTERCEPTOR(SSIZE_T, preadv64, int fd, __sanitizer_iovec *iov, int iovcnt,
|
|
|
|
OFF64_T offset) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, preadv64, fd, iov, iovcnt, offset);
|
2013-10-11 22:13:11 +08:00
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
2013-06-24 18:43:23 +08:00
|
|
|
SSIZE_T res = REAL(preadv64)(fd, iov, iovcnt, offset);
|
|
|
|
if (res > 0) write_iovec(ctx, iov, iovcnt, res);
|
|
|
|
if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PREADV64 COMMON_INTERCEPT_FUNCTION(preadv64)
|
2013-06-24 18:43:23 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PREADV64
|
|
|
|
#endif
|
|
|
|
|
2013-01-18 14:43:13 +08:00
|
|
|
#if SANITIZER_INTERCEPT_WRITE
|
|
|
|
INTERCEPTOR(SSIZE_T, write, int fd, void *ptr, SIZE_T count) {
|
2013-02-11 23:22:34 +08:00
|
|
|
void *ctx;
|
2013-01-18 19:17:23 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, write, fd, ptr, count);
|
2013-10-11 22:13:11 +08:00
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
2013-01-18 14:43:13 +08:00
|
|
|
SSIZE_T res = REAL(write)(fd, ptr, count);
|
2013-06-24 18:43:23 +08:00
|
|
|
// FIXME: this check should be _before_ the call to REAL(write), not after
|
2013-11-11 19:28:30 +08:00
|
|
|
if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
|
2013-01-18 14:43:13 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_WRITE COMMON_INTERCEPT_FUNCTION(write)
|
2013-01-17 22:48:03 +08:00
|
|
|
#else
|
2013-02-11 23:22:34 +08:00
|
|
|
#define INIT_WRITE
|
2013-01-17 22:48:03 +08:00
|
|
|
#endif
|
|
|
|
|
2017-03-30 15:25:33 +08:00
|
|
|
#if SANITIZER_INTERCEPT_FWRITE
|
|
|
|
INTERCEPTOR(SIZE_T, fwrite, const void *p, uptr size, uptr nmemb, void *file) {
|
|
|
|
// libc file streams can call user-supplied functions, see fopencookie.
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fwrite, p, size, nmemb, file);
|
|
|
|
SIZE_T res = REAL(fwrite)(p, size, nmemb, file);
|
|
|
|
if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, p, res * size);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_FWRITE COMMON_INTERCEPT_FUNCTION(fwrite)
|
|
|
|
#else
|
|
|
|
#define INIT_FWRITE
|
|
|
|
#endif
|
|
|
|
|
2013-01-18 14:43:13 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PWRITE
|
2013-01-24 15:44:21 +08:00
|
|
|
INTERCEPTOR(SSIZE_T, pwrite, int fd, void *ptr, SIZE_T count, OFF_T offset) {
|
2013-02-11 23:22:34 +08:00
|
|
|
void *ctx;
|
2013-01-24 15:44:21 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pwrite, fd, ptr, count, offset);
|
2013-10-11 22:13:11 +08:00
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
2013-01-24 15:44:21 +08:00
|
|
|
SSIZE_T res = REAL(pwrite)(fd, ptr, count, offset);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
|
2013-01-18 14:43:13 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PWRITE COMMON_INTERCEPT_FUNCTION(pwrite)
|
2013-01-17 22:48:03 +08:00
|
|
|
#else
|
2013-02-11 23:22:34 +08:00
|
|
|
#define INIT_PWRITE
|
2013-01-17 22:48:03 +08:00
|
|
|
#endif
|
|
|
|
|
2013-01-18 14:43:13 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PWRITE64
|
2013-01-24 15:44:21 +08:00
|
|
|
INTERCEPTOR(SSIZE_T, pwrite64, int fd, void *ptr, OFF64_T count,
|
|
|
|
OFF64_T offset) {
|
2013-02-11 23:22:34 +08:00
|
|
|
void *ctx;
|
2013-01-24 15:44:21 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pwrite64, fd, ptr, count, offset);
|
2013-10-11 22:13:11 +08:00
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
2013-01-24 15:44:21 +08:00
|
|
|
SSIZE_T res = REAL(pwrite64)(fd, ptr, count, offset);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, res);
|
2013-01-18 14:43:13 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PWRITE64 COMMON_INTERCEPT_FUNCTION(pwrite64)
|
2013-01-17 22:48:03 +08:00
|
|
|
#else
|
2013-02-11 23:22:34 +08:00
|
|
|
#define INIT_PWRITE64
|
2013-01-17 22:48:03 +08:00
|
|
|
#endif
|
|
|
|
|
2013-06-24 18:43:23 +08:00
|
|
|
#if SANITIZER_INTERCEPT_WRITEV
|
|
|
|
INTERCEPTOR_WITH_SUFFIX(SSIZE_T, writev, int fd, __sanitizer_iovec *iov,
|
|
|
|
int iovcnt) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, writev, fd, iov, iovcnt);
|
2013-10-11 22:13:11 +08:00
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
2013-06-24 18:43:23 +08:00
|
|
|
if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
|
|
|
SSIZE_T res = REAL(writev)(fd, iov, iovcnt);
|
|
|
|
if (res > 0) read_iovec(ctx, iov, iovcnt, res);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_WRITEV COMMON_INTERCEPT_FUNCTION(writev)
|
2013-06-24 18:43:23 +08:00
|
|
|
#else
|
|
|
|
#define INIT_WRITEV
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PWRITEV
|
|
|
|
INTERCEPTOR(SSIZE_T, pwritev, int fd, __sanitizer_iovec *iov, int iovcnt,
|
|
|
|
OFF_T offset) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pwritev, fd, iov, iovcnt, offset);
|
2013-10-11 22:13:11 +08:00
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
2013-06-24 18:43:23 +08:00
|
|
|
if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
|
|
|
SSIZE_T res = REAL(pwritev)(fd, iov, iovcnt, offset);
|
|
|
|
if (res > 0) read_iovec(ctx, iov, iovcnt, res);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PWRITEV COMMON_INTERCEPT_FUNCTION(pwritev)
|
2013-06-24 18:43:23 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PWRITEV
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PWRITEV64
|
|
|
|
INTERCEPTOR(SSIZE_T, pwritev64, int fd, __sanitizer_iovec *iov, int iovcnt,
|
|
|
|
OFF64_T offset) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pwritev64, fd, iov, iovcnt, offset);
|
2013-10-11 22:13:11 +08:00
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
2013-06-24 18:43:23 +08:00
|
|
|
if (fd >= 0) COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
|
|
|
SSIZE_T res = REAL(pwritev64)(fd, iov, iovcnt, offset);
|
|
|
|
if (res > 0) read_iovec(ctx, iov, iovcnt, res);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PWRITEV64 COMMON_INTERCEPT_FUNCTION(pwritev64)
|
2013-06-24 18:43:23 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PWRITEV64
|
|
|
|
#endif
|
|
|
|
|
2013-01-18 14:43:13 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PRCTL
|
2013-11-11 19:28:30 +08:00
|
|
|
INTERCEPTOR(int, prctl, int option, unsigned long arg2,
|
|
|
|
unsigned long arg3, // NOLINT
|
|
|
|
unsigned long arg4, unsigned long arg5) { // NOLINT
|
2013-02-11 23:22:34 +08:00
|
|
|
void *ctx;
|
2013-01-18 19:17:23 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, prctl, option, arg2, arg3, arg4, arg5);
|
2013-01-18 14:43:13 +08:00
|
|
|
static const int PR_SET_NAME = 15;
|
|
|
|
int res = REAL(prctl(option, arg2, arg3, arg4, arg5));
|
|
|
|
if (option == PR_SET_NAME) {
|
|
|
|
char buff[16];
|
2013-02-11 23:22:34 +08:00
|
|
|
internal_strncpy(buff, (char *)arg2, 15);
|
2013-01-18 14:43:13 +08:00
|
|
|
buff[15] = 0;
|
2013-01-18 19:17:23 +08:00
|
|
|
COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, buff);
|
2013-01-18 14:43:13 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PRCTL COMMON_INTERCEPT_FUNCTION(prctl)
|
2013-01-18 14:43:13 +08:00
|
|
|
#else
|
2013-02-11 23:22:34 +08:00
|
|
|
#define INIT_PRCTL
|
2013-11-11 19:28:30 +08:00
|
|
|
#endif // SANITIZER_INTERCEPT_PRCTL
|
2013-04-08 16:25:22 +08:00
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_TIME
|
|
|
|
INTERCEPTOR(unsigned long, time, unsigned long *t) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, time, t);
|
2014-06-18 17:27:40 +08:00
|
|
|
unsigned long local_t;
|
|
|
|
unsigned long res = REAL(time)(&local_t);
|
2013-04-10 23:13:00 +08:00
|
|
|
if (t && res != (unsigned long)-1) {
|
2013-04-08 16:25:22 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, t, sizeof(*t));
|
2014-06-18 17:27:40 +08:00
|
|
|
*t = local_t;
|
2013-04-08 16:25:22 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_TIME COMMON_INTERCEPT_FUNCTION(time);
|
2013-04-08 16:25:22 +08:00
|
|
|
#else
|
|
|
|
#define INIT_TIME
|
2013-11-11 19:28:30 +08:00
|
|
|
#endif // SANITIZER_INTERCEPT_TIME
|
2013-04-08 16:25:22 +08:00
|
|
|
|
2013-02-19 17:19:16 +08:00
|
|
|
#if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
|
2013-10-02 22:30:03 +08:00
|
|
|
static void unpoison_tm(void *ctx, __sanitizer_tm *tm) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#if !SANITIZER_SOLARIS
|
2013-10-03 22:12:09 +08:00
|
|
|
if (tm->tm_zone) {
|
|
|
|
// Can not use COMMON_INTERCEPTOR_WRITE_RANGE here, because tm->tm_zone
|
|
|
|
// can point to shared memory and tsan would report a data race.
|
2014-03-06 21:26:09 +08:00
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(tm->tm_zone,
|
2013-10-03 22:12:09 +08:00
|
|
|
REAL(strlen(tm->tm_zone)) + 1);
|
|
|
|
}
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#endif
|
2013-10-02 22:30:03 +08:00
|
|
|
}
|
|
|
|
INTERCEPTOR(__sanitizer_tm *, localtime, unsigned long *timep) {
|
2013-02-19 17:19:16 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, localtime, timep);
|
2013-10-02 22:30:03 +08:00
|
|
|
__sanitizer_tm *res = REAL(localtime)(timep);
|
2013-02-19 17:19:16 +08:00
|
|
|
if (res) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
|
2013-10-02 22:30:03 +08:00
|
|
|
unpoison_tm(ctx, res);
|
2013-02-19 17:19:16 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-10-02 22:30:03 +08:00
|
|
|
INTERCEPTOR(__sanitizer_tm *, localtime_r, unsigned long *timep, void *result) {
|
2013-02-19 17:19:16 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, localtime_r, timep, result);
|
2013-10-02 22:30:03 +08:00
|
|
|
__sanitizer_tm *res = REAL(localtime_r)(timep, result);
|
2013-02-19 17:19:16 +08:00
|
|
|
if (res) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
|
2013-10-02 22:30:03 +08:00
|
|
|
unpoison_tm(ctx, res);
|
2013-02-19 17:19:16 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-10-02 22:30:03 +08:00
|
|
|
INTERCEPTOR(__sanitizer_tm *, gmtime, unsigned long *timep) {
|
2013-02-19 17:19:16 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, gmtime, timep);
|
2013-10-02 22:30:03 +08:00
|
|
|
__sanitizer_tm *res = REAL(gmtime)(timep);
|
2013-02-19 17:19:16 +08:00
|
|
|
if (res) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
|
2013-10-02 22:30:03 +08:00
|
|
|
unpoison_tm(ctx, res);
|
2013-02-19 17:19:16 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-10-02 22:30:03 +08:00
|
|
|
INTERCEPTOR(__sanitizer_tm *, gmtime_r, unsigned long *timep, void *result) {
|
2013-02-19 17:19:16 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, gmtime_r, timep, result);
|
2013-10-02 22:30:03 +08:00
|
|
|
__sanitizer_tm *res = REAL(gmtime_r)(timep, result);
|
2013-02-19 17:19:16 +08:00
|
|
|
if (res) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
|
2013-10-02 22:30:03 +08:00
|
|
|
unpoison_tm(ctx, res);
|
2013-02-19 17:19:16 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(char *, ctime, unsigned long *timep) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ctime, timep);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-02-19 17:19:16 +08:00
|
|
|
char *res = REAL(ctime)(timep);
|
|
|
|
if (res) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(char *, ctime_r, unsigned long *timep, char *result) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ctime_r, timep, result);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-02-19 17:19:16 +08:00
|
|
|
char *res = REAL(ctime_r)(timep, result);
|
|
|
|
if (res) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, timep, sizeof(*timep));
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-10-02 22:30:03 +08:00
|
|
|
INTERCEPTOR(char *, asctime, __sanitizer_tm *tm) {
|
2013-02-19 17:19:16 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, asctime, tm);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-02-19 17:19:16 +08:00
|
|
|
char *res = REAL(asctime)(tm);
|
|
|
|
if (res) {
|
2013-10-02 22:30:03 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
|
2013-02-19 17:19:16 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-10-02 22:30:03 +08:00
|
|
|
INTERCEPTOR(char *, asctime_r, __sanitizer_tm *tm, char *result) {
|
2013-02-19 17:19:16 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, asctime_r, tm, result);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-02-19 17:19:16 +08:00
|
|
|
char *res = REAL(asctime_r)(tm, result);
|
|
|
|
if (res) {
|
2013-10-02 22:30:03 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, tm, sizeof(*tm));
|
2013-02-19 17:19:16 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2014-03-28 17:02:57 +08:00
|
|
|
INTERCEPTOR(long, mktime, __sanitizer_tm *tm) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, mktime, tm);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_sec, sizeof(tm->tm_sec));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_min, sizeof(tm->tm_min));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_hour, sizeof(tm->tm_hour));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mday, sizeof(tm->tm_mday));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_mon, sizeof(tm->tm_mon));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_year, sizeof(tm->tm_year));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &tm->tm_isdst, sizeof(tm->tm_isdst));
|
|
|
|
long res = REAL(mktime)(tm);
|
|
|
|
if (res != -1) unpoison_tm(ctx, tm);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_LOCALTIME_AND_FRIENDS \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(localtime); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(localtime_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(gmtime); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(gmtime_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(ctime); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(ctime_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(asctime); \
|
2014-03-28 17:02:57 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION(asctime_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(mktime);
|
2013-02-19 17:19:16 +08:00
|
|
|
#else
|
|
|
|
#define INIT_LOCALTIME_AND_FRIENDS
|
2013-11-11 19:28:30 +08:00
|
|
|
#endif // SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS
|
2013-02-19 17:19:16 +08:00
|
|
|
|
2013-11-02 09:01:35 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STRPTIME
|
|
|
|
INTERCEPTOR(char *, strptime, char *s, char *format, __sanitizer_tm *tm) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strptime, s, format, tm);
|
|
|
|
if (format)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, format, REAL(strlen)(format) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-11-02 09:01:35 +08:00
|
|
|
char *res = REAL(strptime)(s, format, tm);
|
2015-04-07 02:00:26 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, s, res ? res - s : 0);
|
|
|
|
if (res && tm) {
|
2013-11-02 09:01:35 +08:00
|
|
|
// Do not call unpoison_tm here, because strptime does not, in fact,
|
|
|
|
// initialize the entire struct tm. For example, tm_zone pointer is left
|
|
|
|
// uninitialized.
|
2015-04-07 02:00:26 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tm, sizeof(*tm));
|
2013-11-02 09:01:35 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_STRPTIME COMMON_INTERCEPT_FUNCTION(strptime);
|
2013-11-02 09:01:35 +08:00
|
|
|
#else
|
|
|
|
#define INIT_STRPTIME
|
|
|
|
#endif
|
|
|
|
|
2014-01-21 19:58:33 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SCANF || SANITIZER_INTERCEPT_PRINTF
|
2014-01-21 21:01:20 +08:00
|
|
|
#include "sanitizer_common_interceptors_format.inc"
|
2013-01-18 19:17:23 +08:00
|
|
|
|
2014-01-21 19:58:33 +08:00
|
|
|
#define FORMAT_INTERCEPTOR_IMPL(name, vname, ...) \
|
|
|
|
{ \
|
|
|
|
void *ctx; \
|
|
|
|
va_list ap; \
|
|
|
|
va_start(ap, format); \
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__, ap); \
|
2014-02-04 17:35:09 +08:00
|
|
|
int res = WRAP(vname)(__VA_ARGS__, ap); \
|
2014-01-21 19:58:33 +08:00
|
|
|
va_end(ap); \
|
|
|
|
return res; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_SCANF
|
|
|
|
|
2013-02-12 22:29:34 +08:00
|
|
|
#define VSCANF_INTERCEPTOR_IMPL(vname, allowGnuMalloc, ...) \
|
2013-02-12 19:34:52 +08:00
|
|
|
{ \
|
|
|
|
void *ctx; \
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__); \
|
|
|
|
va_list aq; \
|
|
|
|
va_copy(aq, ap); \
|
|
|
|
int res = REAL(vname)(__VA_ARGS__); \
|
|
|
|
if (res > 0) \
|
2013-02-12 22:29:34 +08:00
|
|
|
scanf_common(ctx, res, allowGnuMalloc, format, aq); \
|
2013-02-12 19:34:52 +08:00
|
|
|
va_end(aq); \
|
|
|
|
return res; \
|
|
|
|
}
|
2013-01-18 19:17:23 +08:00
|
|
|
|
2013-02-12 19:34:52 +08:00
|
|
|
INTERCEPTOR(int, vscanf, const char *format, va_list ap)
|
2013-02-12 22:29:34 +08:00
|
|
|
VSCANF_INTERCEPTOR_IMPL(vscanf, true, format, ap)
|
2013-01-18 19:17:23 +08:00
|
|
|
|
2013-02-12 19:34:52 +08:00
|
|
|
INTERCEPTOR(int, vsscanf, const char *str, const char *format, va_list ap)
|
2013-02-12 22:29:34 +08:00
|
|
|
VSCANF_INTERCEPTOR_IMPL(vsscanf, true, str, format, ap)
|
2013-01-18 19:17:23 +08:00
|
|
|
|
2013-02-12 19:34:52 +08:00
|
|
|
INTERCEPTOR(int, vfscanf, void *stream, const char *format, va_list ap)
|
2013-02-12 22:29:34 +08:00
|
|
|
VSCANF_INTERCEPTOR_IMPL(vfscanf, true, stream, format, ap)
|
2013-01-18 19:17:23 +08:00
|
|
|
|
2013-02-20 23:27:58 +08:00
|
|
|
#if SANITIZER_INTERCEPT_ISOC99_SCANF
|
2013-02-12 19:34:52 +08:00
|
|
|
INTERCEPTOR(int, __isoc99_vscanf, const char *format, va_list ap)
|
2013-02-12 22:29:34 +08:00
|
|
|
VSCANF_INTERCEPTOR_IMPL(__isoc99_vscanf, false, format, ap)
|
2013-01-18 19:17:23 +08:00
|
|
|
|
2013-02-12 19:34:52 +08:00
|
|
|
INTERCEPTOR(int, __isoc99_vsscanf, const char *str, const char *format,
|
|
|
|
va_list ap)
|
2013-02-12 22:29:34 +08:00
|
|
|
VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap)
|
2013-02-12 19:34:52 +08:00
|
|
|
|
|
|
|
INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap)
|
2013-02-12 22:29:34 +08:00
|
|
|
VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap)
|
2013-02-20 23:27:58 +08:00
|
|
|
#endif // SANITIZER_INTERCEPT_ISOC99_SCANF
|
2013-02-12 19:34:52 +08:00
|
|
|
|
|
|
|
INTERCEPTOR(int, scanf, const char *format, ...)
|
2014-01-21 19:58:33 +08:00
|
|
|
FORMAT_INTERCEPTOR_IMPL(scanf, vscanf, format)
|
2013-02-12 19:34:52 +08:00
|
|
|
|
|
|
|
INTERCEPTOR(int, fscanf, void *stream, const char *format, ...)
|
2014-01-21 19:58:33 +08:00
|
|
|
FORMAT_INTERCEPTOR_IMPL(fscanf, vfscanf, stream, format)
|
2013-02-12 19:34:52 +08:00
|
|
|
|
|
|
|
INTERCEPTOR(int, sscanf, const char *str, const char *format, ...)
|
2014-01-21 19:58:33 +08:00
|
|
|
FORMAT_INTERCEPTOR_IMPL(sscanf, vsscanf, str, format)
|
2013-02-12 19:34:52 +08:00
|
|
|
|
2013-02-20 23:27:58 +08:00
|
|
|
#if SANITIZER_INTERCEPT_ISOC99_SCANF
|
2013-02-12 19:34:52 +08:00
|
|
|
INTERCEPTOR(int, __isoc99_scanf, const char *format, ...)
|
2014-01-21 19:58:33 +08:00
|
|
|
FORMAT_INTERCEPTOR_IMPL(__isoc99_scanf, __isoc99_vscanf, format)
|
2013-02-12 19:34:52 +08:00
|
|
|
|
|
|
|
INTERCEPTOR(int, __isoc99_fscanf, void *stream, const char *format, ...)
|
2014-01-21 19:58:33 +08:00
|
|
|
FORMAT_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format)
|
2013-02-12 19:34:52 +08:00
|
|
|
|
|
|
|
INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...)
|
2014-01-21 19:58:33 +08:00
|
|
|
FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format)
|
2013-02-20 23:27:58 +08:00
|
|
|
#endif
|
2013-01-18 19:17:23 +08:00
|
|
|
|
2013-08-22 21:59:15 +08:00
|
|
|
#endif
|
2013-01-18 19:17:23 +08:00
|
|
|
|
2013-08-22 21:59:15 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SCANF
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SCANF \
|
2016-11-29 05:15:19 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(scanf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(sscanf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(fscanf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(vscanf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(vsscanf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(vfscanf);
|
2013-01-18 19:17:23 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SCANF
|
|
|
|
#endif
|
|
|
|
|
2013-08-22 21:59:15 +08:00
|
|
|
#if SANITIZER_INTERCEPT_ISOC99_SCANF
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_ISOC99_SCANF \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_scanf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_sscanf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_fscanf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_vscanf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_vsscanf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf);
|
2013-08-22 21:59:15 +08:00
|
|
|
#else
|
|
|
|
#define INIT_ISOC99_SCANF
|
|
|
|
#endif
|
2013-06-07 21:00:47 +08:00
|
|
|
|
2014-01-21 19:58:33 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PRINTF
|
|
|
|
|
|
|
|
#define VPRINTF_INTERCEPTOR_ENTER(vname, ...) \
|
|
|
|
void *ctx; \
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, vname, __VA_ARGS__); \
|
|
|
|
va_list aq; \
|
|
|
|
va_copy(aq, ap);
|
|
|
|
|
|
|
|
#define VPRINTF_INTERCEPTOR_RETURN() \
|
|
|
|
va_end(aq);
|
|
|
|
|
|
|
|
#define VPRINTF_INTERCEPTOR_IMPL(vname, ...) \
|
|
|
|
{ \
|
|
|
|
VPRINTF_INTERCEPTOR_ENTER(vname, __VA_ARGS__); \
|
|
|
|
if (common_flags()->check_printf) \
|
|
|
|
printf_common(ctx, format, aq); \
|
|
|
|
int res = REAL(vname)(__VA_ARGS__); \
|
|
|
|
VPRINTF_INTERCEPTOR_RETURN(); \
|
|
|
|
return res; \
|
|
|
|
}
|
|
|
|
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the REAL() call below may write to freed memory and
|
|
|
|
// corrupt its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-01-21 19:58:33 +08:00
|
|
|
#define VSPRINTF_INTERCEPTOR_IMPL(vname, str, ...) \
|
|
|
|
{ \
|
|
|
|
VPRINTF_INTERCEPTOR_ENTER(vname, str, __VA_ARGS__) \
|
|
|
|
if (common_flags()->check_printf) { \
|
|
|
|
printf_common(ctx, format, aq); \
|
|
|
|
} \
|
|
|
|
int res = REAL(vname)(str, __VA_ARGS__); \
|
2014-05-08 17:18:22 +08:00
|
|
|
if (res >= 0) { \
|
2014-01-21 19:58:33 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, res + 1); \
|
|
|
|
} \
|
|
|
|
VPRINTF_INTERCEPTOR_RETURN(); \
|
|
|
|
return res; \
|
|
|
|
}
|
|
|
|
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the REAL() call below may write to freed memory and
|
|
|
|
// corrupt its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-01-21 19:58:33 +08:00
|
|
|
#define VSNPRINTF_INTERCEPTOR_IMPL(vname, str, size, ...) \
|
|
|
|
{ \
|
|
|
|
VPRINTF_INTERCEPTOR_ENTER(vname, str, size, __VA_ARGS__) \
|
|
|
|
if (common_flags()->check_printf) { \
|
|
|
|
printf_common(ctx, format, aq); \
|
|
|
|
} \
|
|
|
|
int res = REAL(vname)(str, size, __VA_ARGS__); \
|
2014-05-08 17:18:22 +08:00
|
|
|
if (res >= 0) { \
|
2014-01-23 23:09:38 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, str, Min(size, (SIZE_T)(res + 1))); \
|
|
|
|
} \
|
2014-01-21 19:58:33 +08:00
|
|
|
VPRINTF_INTERCEPTOR_RETURN(); \
|
|
|
|
return res; \
|
|
|
|
}
|
|
|
|
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the REAL() call below may write to freed memory and
|
|
|
|
// corrupt its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-01-21 19:58:33 +08:00
|
|
|
#define VASPRINTF_INTERCEPTOR_IMPL(vname, strp, ...) \
|
|
|
|
{ \
|
|
|
|
VPRINTF_INTERCEPTOR_ENTER(vname, strp, __VA_ARGS__) \
|
2014-05-08 17:18:22 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, strp, sizeof(char *)); \
|
2014-01-21 19:58:33 +08:00
|
|
|
if (common_flags()->check_printf) { \
|
|
|
|
printf_common(ctx, format, aq); \
|
|
|
|
} \
|
|
|
|
int res = REAL(vname)(strp, __VA_ARGS__); \
|
2014-05-08 17:18:22 +08:00
|
|
|
if (res >= 0) { \
|
2014-01-21 19:58:33 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *strp, res + 1); \
|
|
|
|
} \
|
|
|
|
VPRINTF_INTERCEPTOR_RETURN(); \
|
|
|
|
return res; \
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, vprintf, const char *format, va_list ap)
|
|
|
|
VPRINTF_INTERCEPTOR_IMPL(vprintf, format, ap)
|
|
|
|
|
2014-05-13 16:36:31 +08:00
|
|
|
INTERCEPTOR(int, vfprintf, __sanitizer_FILE *stream, const char *format,
|
|
|
|
va_list ap)
|
2014-01-21 19:58:33 +08:00
|
|
|
VPRINTF_INTERCEPTOR_IMPL(vfprintf, stream, format, ap)
|
|
|
|
|
|
|
|
INTERCEPTOR(int, vsnprintf, char *str, SIZE_T size, const char *format,
|
|
|
|
va_list ap)
|
|
|
|
VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)
|
|
|
|
|
2017-12-18 23:31:26 +08:00
|
|
|
#if SANITIZER_INTERCEPT___PRINTF_CHK
|
|
|
|
INTERCEPTOR(int, __vsnprintf_chk, char *str, SIZE_T size, int flag,
|
|
|
|
SIZE_T size_to, const char *format, va_list ap)
|
|
|
|
VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf, str, size, format, ap)
|
|
|
|
#endif
|
|
|
|
|
2014-12-22 20:29:40 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PRINTF_L
|
|
|
|
INTERCEPTOR(int, vsnprintf_l, char *str, SIZE_T size, void *loc,
|
|
|
|
const char *format, va_list ap)
|
|
|
|
VSNPRINTF_INTERCEPTOR_IMPL(vsnprintf_l, str, size, loc, format, ap)
|
|
|
|
|
|
|
|
INTERCEPTOR(int, snprintf_l, char *str, SIZE_T size, void *loc,
|
|
|
|
const char *format, ...)
|
|
|
|
FORMAT_INTERCEPTOR_IMPL(snprintf_l, vsnprintf_l, str, size, loc, format)
|
|
|
|
#endif // SANITIZER_INTERCEPT_PRINTF_L
|
|
|
|
|
2014-01-21 19:58:33 +08:00
|
|
|
INTERCEPTOR(int, vsprintf, char *str, const char *format, va_list ap)
|
|
|
|
VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
|
|
|
|
|
2017-12-18 23:31:26 +08:00
|
|
|
#if SANITIZER_INTERCEPT___PRINTF_CHK
|
|
|
|
INTERCEPTOR(int, __vsprintf_chk, char *str, int flag, SIZE_T size_to,
|
|
|
|
const char *format, va_list ap)
|
|
|
|
VSPRINTF_INTERCEPTOR_IMPL(vsprintf, str, format, ap)
|
|
|
|
#endif
|
|
|
|
|
2014-01-21 19:58:33 +08:00
|
|
|
INTERCEPTOR(int, vasprintf, char **strp, const char *format, va_list ap)
|
|
|
|
VASPRINTF_INTERCEPTOR_IMPL(vasprintf, strp, format, ap)
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_ISOC99_PRINTF
|
|
|
|
INTERCEPTOR(int, __isoc99_vprintf, const char *format, va_list ap)
|
|
|
|
VPRINTF_INTERCEPTOR_IMPL(__isoc99_vprintf, format, ap)
|
|
|
|
|
2014-05-13 16:36:31 +08:00
|
|
|
INTERCEPTOR(int, __isoc99_vfprintf, __sanitizer_FILE *stream,
|
|
|
|
const char *format, va_list ap)
|
2014-01-21 19:58:33 +08:00
|
|
|
VPRINTF_INTERCEPTOR_IMPL(__isoc99_vfprintf, stream, format, ap)
|
|
|
|
|
|
|
|
INTERCEPTOR(int, __isoc99_vsnprintf, char *str, SIZE_T size, const char *format,
|
|
|
|
va_list ap)
|
|
|
|
VSNPRINTF_INTERCEPTOR_IMPL(__isoc99_vsnprintf, str, size, format, ap)
|
|
|
|
|
|
|
|
INTERCEPTOR(int, __isoc99_vsprintf, char *str, const char *format,
|
|
|
|
va_list ap)
|
|
|
|
VSPRINTF_INTERCEPTOR_IMPL(__isoc99_vsprintf, str, format,
|
|
|
|
ap)
|
|
|
|
|
|
|
|
#endif // SANITIZER_INTERCEPT_ISOC99_PRINTF
|
|
|
|
|
|
|
|
INTERCEPTOR(int, printf, const char *format, ...)
|
|
|
|
FORMAT_INTERCEPTOR_IMPL(printf, vprintf, format)
|
|
|
|
|
2014-05-13 16:36:31 +08:00
|
|
|
INTERCEPTOR(int, fprintf, __sanitizer_FILE *stream, const char *format, ...)
|
2014-01-21 19:58:33 +08:00
|
|
|
FORMAT_INTERCEPTOR_IMPL(fprintf, vfprintf, stream, format)
|
|
|
|
|
2017-12-18 23:31:26 +08:00
|
|
|
#if SANITIZER_INTERCEPT___PRINTF_CHK
|
|
|
|
INTERCEPTOR(int, __fprintf_chk, __sanitizer_FILE *stream, SIZE_T size,
|
|
|
|
const char *format, ...)
|
|
|
|
FORMAT_INTERCEPTOR_IMPL(__fprintf_chk, vfprintf, stream, format)
|
|
|
|
#endif
|
|
|
|
|
2014-01-21 19:58:33 +08:00
|
|
|
INTERCEPTOR(int, sprintf, char *str, const char *format, ...) // NOLINT
|
|
|
|
FORMAT_INTERCEPTOR_IMPL(sprintf, vsprintf, str, format) // NOLINT
|
|
|
|
|
2017-12-18 23:31:26 +08:00
|
|
|
#if SANITIZER_INTERCEPT___PRINTF_CHK
|
|
|
|
INTERCEPTOR(int, __sprintf_chk, char *str, int flag, SIZE_T size_to,
|
|
|
|
const char *format, ...) // NOLINT
|
|
|
|
FORMAT_INTERCEPTOR_IMPL(__sprintf_chk, vsprintf, str, format) // NOLINT
|
|
|
|
#endif
|
|
|
|
|
2014-01-21 19:58:33 +08:00
|
|
|
INTERCEPTOR(int, snprintf, char *str, SIZE_T size, const char *format, ...)
|
|
|
|
FORMAT_INTERCEPTOR_IMPL(snprintf, vsnprintf, str, size, format)
|
|
|
|
|
2017-12-18 23:31:26 +08:00
|
|
|
#if SANITIZER_INTERCEPT___PRINTF_CHK
|
|
|
|
INTERCEPTOR(int, __snprintf_chk, char *str, SIZE_T size, int flag,
|
|
|
|
SIZE_T size_to, const char *format, ...) // NOLINT
|
|
|
|
FORMAT_INTERCEPTOR_IMPL(__snprintf_chk, vsnprintf, str, size, format) // NOLINT
|
|
|
|
#endif
|
|
|
|
|
2014-01-21 19:58:33 +08:00
|
|
|
INTERCEPTOR(int, asprintf, char **strp, const char *format, ...)
|
|
|
|
FORMAT_INTERCEPTOR_IMPL(asprintf, vasprintf, strp, format)
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_ISOC99_PRINTF
|
|
|
|
INTERCEPTOR(int, __isoc99_printf, const char *format, ...)
|
|
|
|
FORMAT_INTERCEPTOR_IMPL(__isoc99_printf, __isoc99_vprintf, format)
|
|
|
|
|
2014-05-13 16:36:31 +08:00
|
|
|
INTERCEPTOR(int, __isoc99_fprintf, __sanitizer_FILE *stream, const char *format,
|
|
|
|
...)
|
2014-01-21 19:58:33 +08:00
|
|
|
FORMAT_INTERCEPTOR_IMPL(__isoc99_fprintf, __isoc99_vfprintf, stream, format)
|
|
|
|
|
|
|
|
INTERCEPTOR(int, __isoc99_sprintf, char *str, const char *format, ...)
|
|
|
|
FORMAT_INTERCEPTOR_IMPL(__isoc99_sprintf, __isoc99_vsprintf, str, format)
|
|
|
|
|
|
|
|
INTERCEPTOR(int, __isoc99_snprintf, char *str, SIZE_T size,
|
|
|
|
const char *format, ...)
|
|
|
|
FORMAT_INTERCEPTOR_IMPL(__isoc99_snprintf, __isoc99_vsnprintf, str, size,
|
|
|
|
format)
|
|
|
|
|
|
|
|
#endif // SANITIZER_INTERCEPT_ISOC99_PRINTF
|
|
|
|
|
|
|
|
#endif // SANITIZER_INTERCEPT_PRINTF
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PRINTF
|
|
|
|
#define INIT_PRINTF \
|
2016-11-29 05:15:19 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(printf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(sprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(snprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(asprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(fprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(vprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(vsprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(vsnprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(vasprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(vfprintf);
|
2014-01-21 19:58:33 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PRINTF
|
|
|
|
#endif
|
|
|
|
|
2017-12-18 23:31:26 +08:00
|
|
|
#if SANITIZER_INTERCEPT___PRINTF_CHK
|
|
|
|
#define INIT___PRINTF_CHK \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__sprintf_chk); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__snprintf_chk); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__vsprintf_chk); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__vsnprintf_chk); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__fprintf_chk);
|
|
|
|
#else
|
|
|
|
#define INIT___PRINTF_CHK
|
|
|
|
#endif
|
|
|
|
|
2014-12-22 20:29:40 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PRINTF_L
|
|
|
|
#define INIT_PRINTF_L \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(snprintf_l); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(vsnprintf_l);
|
|
|
|
#else
|
|
|
|
#define INIT_PRINTF_L
|
|
|
|
#endif
|
|
|
|
|
2014-01-21 19:58:33 +08:00
|
|
|
#if SANITIZER_INTERCEPT_ISOC99_PRINTF
|
|
|
|
#define INIT_ISOC99_PRINTF \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_printf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_sprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_snprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_fprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_vprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_vsprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_vsnprintf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__isoc99_vfprintf);
|
|
|
|
#else
|
|
|
|
#define INIT_ISOC99_PRINTF
|
|
|
|
#endif
|
|
|
|
|
2013-06-07 21:19:33 +08:00
|
|
|
#if SANITIZER_INTERCEPT_IOCTL
|
2013-06-07 21:00:47 +08:00
|
|
|
#include "sanitizer_common_interceptors_ioctl.inc"
|
[compiler-rt] Fix the prototype of ioctl interceptor
The interceptor of ioctl is using a non-standard prototype:
INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg)
At least on OS X, the request argument should be unsigned long and not
just unsigned, and also instead of the last argument (arg), the function
should be accepting a variable number of arguments, so the prototype
should be:
int ioctl(int fildes, unsigned long request, ...);
We can still keep using `unsigned` internally to save space, because we
know that all possible values of `request` will fit into it.
Reviewed at http://reviews.llvm.org/D7038
llvm-svn: 226926
2015-01-24 03:17:20 +08:00
|
|
|
INTERCEPTOR(int, ioctl, int d, unsigned long request, ...) {
|
2015-02-24 18:10:25 +08:00
|
|
|
// We need a frame pointer, because we call into ioctl_common_[pre|post] which
|
|
|
|
// can trigger a report and we need to be able to unwind through this
|
|
|
|
// function. On Mac in debug mode we might not have a frame pointer, because
|
|
|
|
// ioctl_common_[pre|post] doesn't get inlined here.
|
|
|
|
ENABLE_FRAME_POINTER;
|
|
|
|
|
2013-06-07 21:19:33 +08:00
|
|
|
void *ctx;
|
[compiler-rt] Fix the prototype of ioctl interceptor
The interceptor of ioctl is using a non-standard prototype:
INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg)
At least on OS X, the request argument should be unsigned long and not
just unsigned, and also instead of the last argument (arg), the function
should be accepting a variable number of arguments, so the prototype
should be:
int ioctl(int fildes, unsigned long request, ...);
We can still keep using `unsigned` internally to save space, because we
know that all possible values of `request` will fit into it.
Reviewed at http://reviews.llvm.org/D7038
llvm-svn: 226926
2015-01-24 03:17:20 +08:00
|
|
|
va_list ap;
|
|
|
|
va_start(ap, request);
|
|
|
|
void *arg = va_arg(ap, void *);
|
|
|
|
va_end(ap);
|
2013-06-07 21:19:33 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ioctl, d, request, arg);
|
|
|
|
|
|
|
|
CHECK(ioctl_initialized);
|
|
|
|
|
|
|
|
// Note: TSan does not use common flags, and they are zero-initialized.
|
|
|
|
// This effectively disables ioctl handling in TSan.
|
2013-11-11 19:28:30 +08:00
|
|
|
if (!common_flags()->handle_ioctl) return REAL(ioctl)(d, request, arg);
|
2013-06-07 21:19:33 +08:00
|
|
|
|
[compiler-rt] Fix the prototype of ioctl interceptor
The interceptor of ioctl is using a non-standard prototype:
INTERCEPTOR(int, ioctl, int d, unsigned request, void *arg)
At least on OS X, the request argument should be unsigned long and not
just unsigned, and also instead of the last argument (arg), the function
should be accepting a variable number of arguments, so the prototype
should be:
int ioctl(int fildes, unsigned long request, ...);
We can still keep using `unsigned` internally to save space, because we
know that all possible values of `request` will fit into it.
Reviewed at http://reviews.llvm.org/D7038
llvm-svn: 226926
2015-01-24 03:17:20 +08:00
|
|
|
// Although request is unsigned long, the rest of the interceptor uses it
|
|
|
|
// as just "unsigned" to save space, because we know that all values fit in
|
|
|
|
// "unsigned" - they are compile-time constants.
|
|
|
|
|
2013-06-07 21:19:33 +08:00
|
|
|
const ioctl_desc *desc = ioctl_lookup(request);
|
2014-02-06 03:35:24 +08:00
|
|
|
ioctl_desc decoded_desc;
|
|
|
|
if (!desc) {
|
|
|
|
VPrintf(2, "Decoding unknown ioctl 0x%x\n", request);
|
|
|
|
if (!ioctl_decode(request, &decoded_desc))
|
|
|
|
Printf("WARNING: failed decoding unknown ioctl 0x%x\n", request);
|
|
|
|
else
|
|
|
|
desc = &decoded_desc;
|
|
|
|
}
|
2013-06-07 21:19:33 +08:00
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
if (desc) ioctl_common_pre(ctx, desc, d, request, arg);
|
2013-06-07 21:19:33 +08:00
|
|
|
int res = REAL(ioctl)(d, request, arg);
|
|
|
|
// FIXME: some ioctls have different return values for success and failure.
|
2013-11-11 19:28:30 +08:00
|
|
|
if (desc && res != -1) ioctl_common_post(ctx, desc, res, d, request, arg);
|
2013-06-07 21:19:33 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-06-07 22:56:54 +08:00
|
|
|
#define INIT_IOCTL \
|
|
|
|
ioctl_init(); \
|
2013-11-11 19:28:30 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION(ioctl);
|
2013-06-07 21:19:33 +08:00
|
|
|
#else
|
|
|
|
#define INIT_IOCTL
|
|
|
|
#endif
|
2013-06-07 21:00:47 +08:00
|
|
|
|
2014-03-28 21:03:55 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS || \
|
2014-09-02 20:51:11 +08:00
|
|
|
SANITIZER_INTERCEPT_GETPWENT || SANITIZER_INTERCEPT_FGETPWENT || \
|
|
|
|
SANITIZER_INTERCEPT_GETPWENT_R || SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
|
2014-03-28 21:03:55 +08:00
|
|
|
static void unpoison_passwd(void *ctx, __sanitizer_passwd *pwd) {
|
|
|
|
if (pwd) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwd, sizeof(*pwd));
|
|
|
|
if (pwd->pw_name)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_name,
|
|
|
|
REAL(strlen)(pwd->pw_name) + 1);
|
|
|
|
if (pwd->pw_passwd)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_passwd,
|
|
|
|
REAL(strlen)(pwd->pw_passwd) + 1);
|
|
|
|
#if !SANITIZER_ANDROID
|
|
|
|
if (pwd->pw_gecos)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_gecos,
|
|
|
|
REAL(strlen)(pwd->pw_gecos) + 1);
|
|
|
|
#endif
|
|
|
|
#if SANITIZER_MAC
|
|
|
|
if (pwd->pw_class)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_class,
|
|
|
|
REAL(strlen)(pwd->pw_class) + 1);
|
|
|
|
#endif
|
|
|
|
if (pwd->pw_dir)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_dir,
|
|
|
|
REAL(strlen)(pwd->pw_dir) + 1);
|
|
|
|
if (pwd->pw_shell)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(pwd->pw_shell,
|
|
|
|
REAL(strlen)(pwd->pw_shell) + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void unpoison_group(void *ctx, __sanitizer_group *grp) {
|
|
|
|
if (grp) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, grp, sizeof(*grp));
|
|
|
|
if (grp->gr_name)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_name,
|
|
|
|
REAL(strlen)(grp->gr_name) + 1);
|
|
|
|
if (grp->gr_passwd)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_passwd,
|
|
|
|
REAL(strlen)(grp->gr_passwd) + 1);
|
|
|
|
char **p = grp->gr_mem;
|
|
|
|
for (; *p; ++p) {
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(*p, REAL(strlen)(*p) + 1);
|
|
|
|
}
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(grp->gr_mem,
|
|
|
|
(p - grp->gr_mem + 1) * sizeof(*p));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS ||
|
2014-09-02 20:51:11 +08:00
|
|
|
// SANITIZER_INTERCEPT_GETPWENT || SANITIZER_INTERCEPT_FGETPWENT ||
|
|
|
|
// SANITIZER_INTERCEPT_GETPWENT_R ||
|
|
|
|
// SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
|
2014-03-28 21:03:55 +08:00
|
|
|
|
2013-04-23 20:01:20 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(__sanitizer_passwd *, getpwnam, const char *name) {
|
2013-04-01 22:47:21 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getpwnam, name);
|
2017-11-30 03:33:35 +08:00
|
|
|
if (name)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
|
2014-03-28 21:03:55 +08:00
|
|
|
__sanitizer_passwd *res = REAL(getpwnam)(name);
|
2015-09-30 02:23:36 +08:00
|
|
|
if (res) unpoison_passwd(ctx, res);
|
2013-04-01 22:47:21 +08:00
|
|
|
return res;
|
|
|
|
}
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(__sanitizer_passwd *, getpwuid, u32 uid) {
|
2013-04-01 22:47:21 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getpwuid, uid);
|
2014-03-28 21:03:55 +08:00
|
|
|
__sanitizer_passwd *res = REAL(getpwuid)(uid);
|
2015-09-30 02:23:36 +08:00
|
|
|
if (res) unpoison_passwd(ctx, res);
|
2013-04-01 22:47:21 +08:00
|
|
|
return res;
|
|
|
|
}
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(__sanitizer_group *, getgrnam, const char *name) {
|
2013-04-23 20:01:20 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getgrnam, name);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
|
2014-03-28 21:03:55 +08:00
|
|
|
__sanitizer_group *res = REAL(getgrnam)(name);
|
2015-09-30 02:23:36 +08:00
|
|
|
if (res) unpoison_group(ctx, res);
|
2013-04-23 20:01:20 +08:00
|
|
|
return res;
|
|
|
|
}
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(__sanitizer_group *, getgrgid, u32 gid) {
|
2013-04-23 20:01:20 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getgrgid, gid);
|
2014-03-28 21:03:55 +08:00
|
|
|
__sanitizer_group *res = REAL(getgrgid)(gid);
|
2015-09-30 02:23:36 +08:00
|
|
|
if (res) unpoison_group(ctx, res);
|
2013-04-23 20:01:20 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GETPWNAM_AND_FRIENDS \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getpwnam); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getpwuid); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getgrnam); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getgrgid);
|
2013-04-01 22:47:21 +08:00
|
|
|
#else
|
2013-04-23 20:01:20 +08:00
|
|
|
#define INIT_GETPWNAM_AND_FRIENDS
|
2013-04-01 22:47:21 +08:00
|
|
|
#endif
|
|
|
|
|
2013-04-23 20:01:20 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETPWNAM_R_AND_FRIENDS
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(int, getpwnam_r, const char *name, __sanitizer_passwd *pwd,
|
|
|
|
char *buf, SIZE_T buflen, __sanitizer_passwd **result) {
|
2013-04-01 22:47:21 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getpwnam_r, name, pwd, buf, buflen, result);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-01 22:47:21 +08:00
|
|
|
int res = REAL(getpwnam_r)(name, pwd, buf, buflen, result);
|
|
|
|
if (!res) {
|
2014-05-14 20:32:40 +08:00
|
|
|
if (result && *result) unpoison_passwd(ctx, *result);
|
2013-04-01 22:47:21 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
|
|
|
|
}
|
2014-02-14 20:32:15 +08:00
|
|
|
if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
2013-04-01 22:47:21 +08:00
|
|
|
return res;
|
|
|
|
}
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(int, getpwuid_r, u32 uid, __sanitizer_passwd *pwd, char *buf,
|
|
|
|
SIZE_T buflen, __sanitizer_passwd **result) {
|
2013-04-01 22:47:21 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getpwuid_r, uid, pwd, buf, buflen, result);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-01 22:47:21 +08:00
|
|
|
int res = REAL(getpwuid_r)(uid, pwd, buf, buflen, result);
|
|
|
|
if (!res) {
|
2014-05-14 20:32:40 +08:00
|
|
|
if (result && *result) unpoison_passwd(ctx, *result);
|
2013-04-01 22:47:21 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
|
|
|
|
}
|
2014-02-14 20:32:15 +08:00
|
|
|
if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
2013-04-01 22:47:21 +08:00
|
|
|
return res;
|
|
|
|
}
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(int, getgrnam_r, const char *name, __sanitizer_group *grp,
|
|
|
|
char *buf, SIZE_T buflen, __sanitizer_group **result) {
|
2013-04-23 20:01:20 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getgrnam_r, name, grp, buf, buflen, result);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-23 20:01:20 +08:00
|
|
|
int res = REAL(getgrnam_r)(name, grp, buf, buflen, result);
|
|
|
|
if (!res) {
|
2014-05-14 20:32:40 +08:00
|
|
|
if (result && *result) unpoison_group(ctx, *result);
|
2013-04-23 20:01:20 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
|
|
|
|
}
|
2014-02-14 20:32:15 +08:00
|
|
|
if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
2013-04-23 20:01:20 +08:00
|
|
|
return res;
|
|
|
|
}
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(int, getgrgid_r, u32 gid, __sanitizer_group *grp, char *buf,
|
|
|
|
SIZE_T buflen, __sanitizer_group **result) {
|
2013-04-23 20:01:20 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getgrgid_r, gid, grp, buf, buflen, result);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-23 20:01:20 +08:00
|
|
|
int res = REAL(getgrgid_r)(gid, grp, buf, buflen, result);
|
|
|
|
if (!res) {
|
2014-05-14 20:32:40 +08:00
|
|
|
if (result && *result) unpoison_group(ctx, *result);
|
2013-04-23 20:01:20 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
|
|
|
|
}
|
2014-02-14 20:32:15 +08:00
|
|
|
if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
2013-04-23 20:01:20 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GETPWNAM_R_AND_FRIENDS \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getpwnam_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getpwuid_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getgrnam_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getgrgid_r);
|
2013-04-01 22:47:21 +08:00
|
|
|
#else
|
2013-04-23 20:01:20 +08:00
|
|
|
#define INIT_GETPWNAM_R_AND_FRIENDS
|
2013-04-01 22:47:21 +08:00
|
|
|
#endif
|
|
|
|
|
2014-03-28 18:56:07 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETPWENT
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(__sanitizer_passwd *, getpwent, int dummy) {
|
2014-03-28 18:56:07 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getpwent, dummy);
|
2014-03-28 21:03:55 +08:00
|
|
|
__sanitizer_passwd *res = REAL(getpwent)(dummy);
|
2015-09-30 02:23:36 +08:00
|
|
|
if (res) unpoison_passwd(ctx, res);
|
2014-03-28 18:56:07 +08:00
|
|
|
return res;
|
|
|
|
}
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(__sanitizer_group *, getgrent, int dummy) {
|
2014-03-28 18:56:07 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getgrent, dummy);
|
2014-03-28 21:03:55 +08:00
|
|
|
__sanitizer_group *res = REAL(getgrent)(dummy);
|
2015-09-30 02:23:36 +08:00
|
|
|
if (res) unpoison_group(ctx, res);;
|
2014-03-28 18:56:07 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_GETPWENT \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getpwent); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getgrent);
|
|
|
|
#else
|
|
|
|
#define INIT_GETPWENT
|
|
|
|
#endif
|
|
|
|
|
2014-03-28 21:03:55 +08:00
|
|
|
#if SANITIZER_INTERCEPT_FGETPWENT
|
|
|
|
INTERCEPTOR(__sanitizer_passwd *, fgetpwent, void *fp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent, fp);
|
|
|
|
__sanitizer_passwd *res = REAL(fgetpwent)(fp);
|
2015-09-30 02:23:36 +08:00
|
|
|
if (res) unpoison_passwd(ctx, res);
|
2014-03-28 21:03:55 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(__sanitizer_group *, fgetgrent, void *fp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent, fp);
|
|
|
|
__sanitizer_group *res = REAL(fgetgrent)(fp);
|
2015-09-30 02:23:36 +08:00
|
|
|
if (res) unpoison_group(ctx, res);
|
2014-03-28 21:03:55 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_FGETPWENT \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fgetpwent); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fgetgrent);
|
|
|
|
#else
|
|
|
|
#define INIT_FGETPWENT
|
|
|
|
#endif
|
|
|
|
|
2014-03-28 18:56:07 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETPWENT_R
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(int, getpwent_r, __sanitizer_passwd *pwbuf, char *buf,
|
|
|
|
SIZE_T buflen, __sanitizer_passwd **pwbufp) {
|
2014-03-28 18:56:07 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getpwent_r, pwbuf, buf, buflen, pwbufp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-03-28 18:56:07 +08:00
|
|
|
int res = REAL(getpwent_r)(pwbuf, buf, buflen, pwbufp);
|
|
|
|
if (!res) {
|
2014-05-14 20:32:40 +08:00
|
|
|
if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp);
|
2014-03-28 18:56:07 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
|
|
|
|
}
|
|
|
|
if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
|
|
|
|
return res;
|
|
|
|
}
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(int, fgetpwent_r, void *fp, __sanitizer_passwd *pwbuf, char *buf,
|
|
|
|
SIZE_T buflen, __sanitizer_passwd **pwbufp) {
|
2014-03-28 18:56:07 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fgetpwent_r, fp, pwbuf, buf, buflen, pwbufp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-03-28 18:56:07 +08:00
|
|
|
int res = REAL(fgetpwent_r)(fp, pwbuf, buf, buflen, pwbufp);
|
|
|
|
if (!res) {
|
2014-05-14 20:32:40 +08:00
|
|
|
if (pwbufp && *pwbufp) unpoison_passwd(ctx, *pwbufp);
|
2014-03-28 18:56:07 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
|
|
|
|
}
|
|
|
|
if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
|
|
|
|
return res;
|
|
|
|
}
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(int, getgrent_r, __sanitizer_group *pwbuf, char *buf, SIZE_T buflen,
|
|
|
|
__sanitizer_group **pwbufp) {
|
2014-03-28 18:56:07 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getgrent_r, pwbuf, buf, buflen, pwbufp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-03-28 18:56:07 +08:00
|
|
|
int res = REAL(getgrent_r)(pwbuf, buf, buflen, pwbufp);
|
|
|
|
if (!res) {
|
2014-05-14 20:32:40 +08:00
|
|
|
if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp);
|
2014-03-28 18:56:07 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
|
|
|
|
}
|
|
|
|
if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
|
|
|
|
return res;
|
|
|
|
}
|
2014-03-28 21:03:55 +08:00
|
|
|
INTERCEPTOR(int, fgetgrent_r, void *fp, __sanitizer_group *pwbuf, char *buf,
|
|
|
|
SIZE_T buflen, __sanitizer_group **pwbufp) {
|
2014-03-28 18:56:07 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fgetgrent_r, fp, pwbuf, buf, buflen, pwbufp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-03-28 18:56:07 +08:00
|
|
|
int res = REAL(fgetgrent_r)(fp, pwbuf, buf, buflen, pwbufp);
|
|
|
|
if (!res) {
|
2014-05-14 20:32:40 +08:00
|
|
|
if (pwbufp && *pwbufp) unpoison_group(ctx, *pwbufp);
|
2014-03-28 18:56:07 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, buflen);
|
|
|
|
}
|
|
|
|
if (pwbufp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pwbufp, sizeof(*pwbufp));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_GETPWENT_R \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getpwent_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fgetpwent_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getgrent_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fgetgrent_r);
|
|
|
|
#else
|
|
|
|
#define INIT_GETPWENT_R
|
|
|
|
#endif
|
|
|
|
|
2014-03-28 19:46:35 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SETPWENT
|
|
|
|
// The only thing these interceptors do is disable any nested interceptors.
|
|
|
|
// These functions may open nss modules and call uninstrumented functions from
|
|
|
|
// them, and we don't want things like strlen() to trigger.
|
|
|
|
INTERCEPTOR(void, setpwent, int dummy) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, setpwent, dummy);
|
|
|
|
REAL(setpwent)(dummy);
|
|
|
|
}
|
|
|
|
INTERCEPTOR(void, endpwent, int dummy) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, endpwent, dummy);
|
|
|
|
REAL(endpwent)(dummy);
|
|
|
|
}
|
|
|
|
INTERCEPTOR(void, setgrent, int dummy) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, setgrent, dummy);
|
|
|
|
REAL(setgrent)(dummy);
|
|
|
|
}
|
|
|
|
INTERCEPTOR(void, endgrent, int dummy) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, endgrent, dummy);
|
|
|
|
REAL(endgrent)(dummy);
|
|
|
|
}
|
|
|
|
#define INIT_SETPWENT \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(setpwent); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(endpwent); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(setgrent); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(endgrent);
|
|
|
|
#else
|
|
|
|
#define INIT_SETPWENT
|
|
|
|
#endif
|
|
|
|
|
2013-04-01 22:47:21 +08:00
|
|
|
#if SANITIZER_INTERCEPT_CLOCK_GETTIME
|
|
|
|
INTERCEPTOR(int, clock_getres, u32 clk_id, void *tp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, clock_getres, clk_id, tp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-01 22:47:21 +08:00
|
|
|
int res = REAL(clock_getres)(clk_id, tp);
|
2013-04-23 19:48:31 +08:00
|
|
|
if (!res && tp) {
|
2013-04-01 22:47:21 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, clock_gettime, u32 clk_id, void *tp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, clock_gettime, clk_id, tp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-01 22:47:21 +08:00
|
|
|
int res = REAL(clock_gettime)(clk_id, tp);
|
|
|
|
if (!res) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, struct_timespec_sz);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2017-12-14 00:23:54 +08:00
|
|
|
namespace __sanitizer {
|
|
|
|
extern "C" {
|
|
|
|
int real_clock_gettime(u32 clk_id, void *tp) {
|
|
|
|
return REAL(clock_gettime)(clk_id, tp);
|
|
|
|
}
|
|
|
|
} // extern "C"
|
|
|
|
} // namespace __sanitizer
|
2013-04-01 22:47:21 +08:00
|
|
|
INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, clock_settime, clk_id, tp);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, tp, struct_timespec_sz);
|
|
|
|
return REAL(clock_settime)(clk_id, tp);
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_CLOCK_GETTIME \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(clock_getres); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(clock_gettime); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(clock_settime);
|
2013-04-01 22:47:21 +08:00
|
|
|
#else
|
|
|
|
#define INIT_CLOCK_GETTIME
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_GETITIMER
|
|
|
|
INTERCEPTOR(int, getitimer, int which, void *curr_value) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getitimer, which, curr_value);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-01 22:47:21 +08:00
|
|
|
int res = REAL(getitimer)(which, curr_value);
|
2013-08-06 17:54:33 +08:00
|
|
|
if (!res && curr_value) {
|
2013-04-01 22:47:21 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerval_sz);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, setitimer, int which, const void *new_value, void *old_value) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, setitimer, which, new_value, old_value);
|
Correct the setitimer interceptor on NetBSD
Summary:
itimerval can contain padding that may be legitimately uninitialized.
On NetBSD there are four integers of type "long, int, long, int", the
int argument stands for __sanitizer_suseconds_t. Compiler adds extra
padding in this layout.
Check every field of struct itimerval separately.
Define __sanitizer_suseconds_t as long on FreeBSD, Linux and SmartOS,
and int on NetBSD. Define __sanitizer_timeval and __sanitizer_itimerval.
Sponsored by <The NetBSD Foundation>
Reviewers: eugenis, joerg, vitalybuka
Reviewed By: vitalybuka
Subscribers: emaste, kubamracek, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D41502
llvm-svn: 322399
2018-01-13 04:45:56 +08:00
|
|
|
if (new_value) {
|
|
|
|
// itimerval can contain padding that may be legitimately uninitialized
|
|
|
|
const struct __sanitizer_itimerval *nv =
|
|
|
|
(const struct __sanitizer_itimerval *)new_value;
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_sec,
|
|
|
|
sizeof(__sanitizer_time_t));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_interval.tv_usec,
|
|
|
|
sizeof(__sanitizer_suseconds_t));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_sec,
|
|
|
|
sizeof(__sanitizer_time_t));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &nv->it_value.tv_usec,
|
|
|
|
sizeof(__sanitizer_suseconds_t));
|
|
|
|
}
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-01 22:47:21 +08:00
|
|
|
int res = REAL(setitimer)(which, new_value, old_value);
|
|
|
|
if (!res && old_value) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerval_sz);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GETITIMER \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getitimer); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(setitimer);
|
2013-04-01 22:47:21 +08:00
|
|
|
#else
|
|
|
|
#define INIT_GETITIMER
|
|
|
|
#endif
|
|
|
|
|
2013-04-09 19:35:13 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GLOB
|
2013-07-02 22:08:52 +08:00
|
|
|
static void unpoison_glob_t(void *ctx, __sanitizer_glob_t *pglob) {
|
2013-04-09 19:35:13 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, pglob, sizeof(*pglob));
|
|
|
|
// +1 for NULL pointer at the end.
|
2013-07-02 22:08:52 +08:00
|
|
|
if (pglob->gl_pathv)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(
|
|
|
|
ctx, pglob->gl_pathv, (pglob->gl_pathc + 1) * sizeof(*pglob->gl_pathv));
|
2013-04-09 19:35:13 +08:00
|
|
|
for (SIZE_T i = 0; i < pglob->gl_pathc; ++i) {
|
|
|
|
char *p = pglob->gl_pathv[i];
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, REAL(strlen)(p) + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#if SANITIZER_SOLARIS
|
|
|
|
INTERCEPTOR(int, glob, const char *pattern, int flags,
|
|
|
|
int (*errfunc)(const char *epath, int eerrno),
|
|
|
|
__sanitizer_glob_t *pglob) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
|
|
|
|
int res = REAL(glob)(pattern, flags, errfunc, pglob);
|
|
|
|
if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#else
|
2013-11-11 19:28:30 +08:00
|
|
|
static THREADLOCAL __sanitizer_glob_t *pglob_copy;
|
2013-07-09 20:07:59 +08:00
|
|
|
|
|
|
|
static void wrapped_gl_closedir(void *dir) {
|
2014-03-06 21:26:09 +08:00
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
|
2014-11-18 18:33:15 +08:00
|
|
|
pglob_copy->gl_closedir(dir);
|
2013-07-09 20:07:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void *wrapped_gl_readdir(void *dir) {
|
2014-03-06 21:26:09 +08:00
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
|
2014-11-18 18:33:15 +08:00
|
|
|
return pglob_copy->gl_readdir(dir);
|
2013-07-09 20:07:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void *wrapped_gl_opendir(const char *s) {
|
2014-03-06 21:26:09 +08:00
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
|
2014-11-18 18:33:15 +08:00
|
|
|
return pglob_copy->gl_opendir(s);
|
2013-07-09 20:07:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int wrapped_gl_lstat(const char *s, void *st) {
|
2014-03-06 21:26:09 +08:00
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
|
2014-11-18 18:33:15 +08:00
|
|
|
return pglob_copy->gl_lstat(s, st);
|
2013-07-09 20:07:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int wrapped_gl_stat(const char *s, void *st) {
|
2014-03-06 21:26:09 +08:00
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(s, REAL(strlen)(s) + 1);
|
2014-11-18 18:33:15 +08:00
|
|
|
return pglob_copy->gl_stat(s, st);
|
2013-07-09 20:07:59 +08:00
|
|
|
}
|
|
|
|
|
2015-12-11 03:24:27 +08:00
|
|
|
static const __sanitizer_glob_t kGlobCopy = {
|
|
|
|
0, 0, 0,
|
|
|
|
0, wrapped_gl_closedir, wrapped_gl_readdir,
|
|
|
|
wrapped_gl_opendir, wrapped_gl_lstat, wrapped_gl_stat};
|
|
|
|
|
2013-04-09 19:35:13 +08:00
|
|
|
INTERCEPTOR(int, glob, const char *pattern, int flags,
|
|
|
|
int (*errfunc)(const char *epath, int eerrno),
|
2013-07-02 22:08:52 +08:00
|
|
|
__sanitizer_glob_t *pglob) {
|
2013-04-09 19:35:13 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, glob, pattern, flags, errfunc, pglob);
|
2015-04-07 02:00:26 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
|
2015-12-11 03:24:27 +08:00
|
|
|
__sanitizer_glob_t glob_copy;
|
|
|
|
internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
|
2013-07-09 20:07:59 +08:00
|
|
|
if (flags & glob_altdirfunc) {
|
|
|
|
Swap(pglob->gl_closedir, glob_copy.gl_closedir);
|
|
|
|
Swap(pglob->gl_readdir, glob_copy.gl_readdir);
|
|
|
|
Swap(pglob->gl_opendir, glob_copy.gl_opendir);
|
|
|
|
Swap(pglob->gl_lstat, glob_copy.gl_lstat);
|
|
|
|
Swap(pglob->gl_stat, glob_copy.gl_stat);
|
|
|
|
pglob_copy = &glob_copy;
|
|
|
|
}
|
2013-04-09 19:35:13 +08:00
|
|
|
int res = REAL(glob)(pattern, flags, errfunc, pglob);
|
2013-07-09 20:07:59 +08:00
|
|
|
if (flags & glob_altdirfunc) {
|
|
|
|
Swap(pglob->gl_closedir, glob_copy.gl_closedir);
|
|
|
|
Swap(pglob->gl_readdir, glob_copy.gl_readdir);
|
|
|
|
Swap(pglob->gl_opendir, glob_copy.gl_opendir);
|
|
|
|
Swap(pglob->gl_lstat, glob_copy.gl_lstat);
|
|
|
|
Swap(pglob->gl_stat, glob_copy.gl_stat);
|
|
|
|
}
|
|
|
|
pglob_copy = 0;
|
2013-07-02 22:08:52 +08:00
|
|
|
if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
|
2013-04-09 19:35:13 +08:00
|
|
|
return res;
|
|
|
|
}
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#endif // SANITIZER_SOLARIS
|
|
|
|
#define INIT_GLOB \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(glob);
|
|
|
|
#else // SANITIZER_INTERCEPT_GLOB
|
|
|
|
#define INIT_GLOB
|
|
|
|
#endif // SANITIZER_INTERCEPT_GLOB
|
2013-04-09 19:35:13 +08:00
|
|
|
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GLOB64
|
2013-04-09 19:35:13 +08:00
|
|
|
INTERCEPTOR(int, glob64, const char *pattern, int flags,
|
|
|
|
int (*errfunc)(const char *epath, int eerrno),
|
2013-07-02 22:08:52 +08:00
|
|
|
__sanitizer_glob_t *pglob) {
|
2013-04-09 19:35:13 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, glob64, pattern, flags, errfunc, pglob);
|
2015-04-07 02:00:26 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, pattern, 0);
|
2015-12-11 03:24:27 +08:00
|
|
|
__sanitizer_glob_t glob_copy;
|
|
|
|
internal_memcpy(&glob_copy, &kGlobCopy, sizeof(glob_copy));
|
2013-07-09 20:34:25 +08:00
|
|
|
if (flags & glob_altdirfunc) {
|
|
|
|
Swap(pglob->gl_closedir, glob_copy.gl_closedir);
|
|
|
|
Swap(pglob->gl_readdir, glob_copy.gl_readdir);
|
|
|
|
Swap(pglob->gl_opendir, glob_copy.gl_opendir);
|
|
|
|
Swap(pglob->gl_lstat, glob_copy.gl_lstat);
|
|
|
|
Swap(pglob->gl_stat, glob_copy.gl_stat);
|
|
|
|
pglob_copy = &glob_copy;
|
|
|
|
}
|
2013-04-09 19:35:13 +08:00
|
|
|
int res = REAL(glob64)(pattern, flags, errfunc, pglob);
|
2013-07-09 20:34:25 +08:00
|
|
|
if (flags & glob_altdirfunc) {
|
|
|
|
Swap(pglob->gl_closedir, glob_copy.gl_closedir);
|
|
|
|
Swap(pglob->gl_readdir, glob_copy.gl_readdir);
|
|
|
|
Swap(pglob->gl_opendir, glob_copy.gl_opendir);
|
|
|
|
Swap(pglob->gl_lstat, glob_copy.gl_lstat);
|
|
|
|
Swap(pglob->gl_stat, glob_copy.gl_stat);
|
|
|
|
}
|
|
|
|
pglob_copy = 0;
|
2013-07-02 22:08:52 +08:00
|
|
|
if ((!res || res == glob_nomatch) && pglob) unpoison_glob_t(ctx, pglob);
|
2013-04-09 19:35:13 +08:00
|
|
|
return res;
|
|
|
|
}
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#define INIT_GLOB64 \
|
2013-11-11 19:28:30 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION(glob64);
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#else // SANITIZER_INTERCEPT_GLOB64
|
|
|
|
#define INIT_GLOB64
|
|
|
|
#endif // SANITIZER_INTERCEPT_GLOB64
|
2013-04-09 19:35:13 +08:00
|
|
|
|
2013-04-09 22:34:59 +08:00
|
|
|
#if SANITIZER_INTERCEPT_WAIT
|
2013-05-20 21:32:35 +08:00
|
|
|
// According to sys/wait.h, wait(), waitid(), waitpid() may have symbol version
|
|
|
|
// suffixes on Darwin. See the declaration of INTERCEPTOR_WITH_SUFFIX for
|
|
|
|
// details.
|
|
|
|
INTERCEPTOR_WITH_SUFFIX(int, wait, int *status) {
|
2013-04-09 22:34:59 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, wait, status);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-09 22:34:59 +08:00
|
|
|
int res = REAL(wait)(status);
|
2013-04-29 17:04:24 +08:00
|
|
|
if (res != -1 && status)
|
2013-04-09 22:34:59 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
|
|
|
|
return res;
|
|
|
|
}
|
2014-08-02 03:33:14 +08:00
|
|
|
// On FreeBSD id_t is always 64-bit wide.
|
|
|
|
#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32)
|
|
|
|
INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, long long id, void *infop,
|
|
|
|
int options) {
|
|
|
|
#else
|
2013-05-22 16:54:30 +08:00
|
|
|
INTERCEPTOR_WITH_SUFFIX(int, waitid, int idtype, int id, void *infop,
|
2013-11-11 19:28:30 +08:00
|
|
|
int options) {
|
2014-08-02 03:33:14 +08:00
|
|
|
#endif
|
2013-04-09 22:34:59 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, waitid, idtype, id, infop, options);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-09 22:34:59 +08:00
|
|
|
int res = REAL(waitid)(idtype, id, infop, options);
|
2013-04-29 17:04:24 +08:00
|
|
|
if (res != -1 && infop)
|
2013-04-09 22:34:59 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, infop, siginfo_t_sz);
|
|
|
|
return res;
|
|
|
|
}
|
2013-05-20 21:32:35 +08:00
|
|
|
INTERCEPTOR_WITH_SUFFIX(int, waitpid, int pid, int *status, int options) {
|
2013-04-09 22:34:59 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, waitpid, pid, status, options);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-09 22:34:59 +08:00
|
|
|
int res = REAL(waitpid)(pid, status, options);
|
2013-04-29 17:04:24 +08:00
|
|
|
if (res != -1 && status)
|
2013-04-09 22:34:59 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, wait3, int *status, int options, void *rusage) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, wait3, status, options, rusage);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-09 22:34:59 +08:00
|
|
|
int res = REAL(wait3)(status, options, rusage);
|
|
|
|
if (res != -1) {
|
2013-11-11 19:28:30 +08:00
|
|
|
if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
|
|
|
|
if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
|
2013-04-09 22:34:59 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2014-02-12 21:05:17 +08:00
|
|
|
#if SANITIZER_ANDROID
|
|
|
|
INTERCEPTOR(int, __wait4, int pid, int *status, int options, void *rusage) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __wait4, pid, status, options, rusage);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-02-12 21:05:17 +08:00
|
|
|
int res = REAL(__wait4)(pid, status, options, rusage);
|
|
|
|
if (res != -1) {
|
|
|
|
if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
|
|
|
|
if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(__wait4);
|
|
|
|
#else
|
2013-04-09 22:34:59 +08:00
|
|
|
INTERCEPTOR(int, wait4, int pid, int *status, int options, void *rusage) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, wait4, pid, status, options, rusage);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-09 22:34:59 +08:00
|
|
|
int res = REAL(wait4)(pid, status, options, rusage);
|
|
|
|
if (res != -1) {
|
2013-11-11 19:28:30 +08:00
|
|
|
if (status) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, status, sizeof(*status));
|
|
|
|
if (rusage) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rusage, struct_rusage_sz);
|
2013-04-09 22:34:59 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2014-02-12 21:05:17 +08:00
|
|
|
#define INIT_WAIT4 COMMON_INTERCEPT_FUNCTION(wait4);
|
|
|
|
#endif // SANITIZER_ANDROID
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_WAIT \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(wait); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(waitid); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(waitpid); \
|
2014-02-12 21:05:17 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION(wait3);
|
2013-04-09 22:34:59 +08:00
|
|
|
#else
|
|
|
|
#define INIT_WAIT
|
2014-02-12 21:05:17 +08:00
|
|
|
#define INIT_WAIT4
|
2013-04-09 22:34:59 +08:00
|
|
|
#endif
|
|
|
|
|
2013-04-23 22:05:15 +08:00
|
|
|
#if SANITIZER_INTERCEPT_INET
|
|
|
|
INTERCEPTOR(char *, inet_ntop, int af, const void *src, char *dst, u32 size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, inet_ntop, af, src, dst, size);
|
|
|
|
uptr sz = __sanitizer_in_addr_sz(af);
|
|
|
|
if (sz) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sz);
|
|
|
|
// FIXME: figure out read size based on the address family.
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-23 22:05:15 +08:00
|
|
|
char *res = REAL(inet_ntop)(af, src, dst, size);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
|
2013-04-23 22:05:15 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, inet_pton, int af, const char *src, void *dst) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, inet_pton, af, src, dst);
|
2015-04-07 02:00:26 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, src, 0);
|
2013-04-23 22:05:15 +08:00
|
|
|
// FIXME: figure out read size based on the address family.
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-04-23 22:05:15 +08:00
|
|
|
int res = REAL(inet_pton)(af, src, dst);
|
|
|
|
if (res == 1) {
|
|
|
|
uptr sz = __sanitizer_in_addr_sz(af);
|
|
|
|
if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_INET \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(inet_ntop); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(inet_pton);
|
2013-04-23 22:05:15 +08:00
|
|
|
#else
|
|
|
|
#define INIT_INET
|
|
|
|
#endif
|
|
|
|
|
2013-06-24 21:56:14 +08:00
|
|
|
#if SANITIZER_INTERCEPT_INET
|
|
|
|
INTERCEPTOR(int, inet_aton, const char *cp, void *dst) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, inet_aton, cp, dst);
|
|
|
|
if (cp) COMMON_INTERCEPTOR_READ_RANGE(ctx, cp, REAL(strlen)(cp) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-06-24 21:56:14 +08:00
|
|
|
int res = REAL(inet_aton)(cp, dst);
|
|
|
|
if (res != 0) {
|
|
|
|
uptr sz = __sanitizer_in_addr_sz(af_inet);
|
|
|
|
if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sz);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_INET_ATON COMMON_INTERCEPT_FUNCTION(inet_aton);
|
2013-06-24 21:56:14 +08:00
|
|
|
#else
|
|
|
|
#define INIT_INET_ATON
|
|
|
|
#endif
|
|
|
|
|
2013-05-21 16:12:08 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM
|
|
|
|
INTERCEPTOR(int, pthread_getschedparam, uptr thread, int *policy, int *param) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pthread_getschedparam, thread, policy, param);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-05-21 16:12:08 +08:00
|
|
|
int res = REAL(pthread_getschedparam)(thread, policy, param);
|
|
|
|
if (res == 0) {
|
|
|
|
if (policy) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, policy, sizeof(*policy));
|
|
|
|
if (param) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, sizeof(*param));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PTHREAD_GETSCHEDPARAM \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_getschedparam);
|
2013-05-21 16:12:08 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_GETSCHEDPARAM
|
|
|
|
#endif
|
2013-04-09 22:34:59 +08:00
|
|
|
|
2013-05-22 20:50:26 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETADDRINFO
|
|
|
|
INTERCEPTOR(int, getaddrinfo, char *node, char *service,
|
|
|
|
struct __sanitizer_addrinfo *hints,
|
|
|
|
struct __sanitizer_addrinfo **out) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
|
|
|
|
if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
|
|
|
|
if (service)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
|
|
|
|
if (hints)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-05-22 20:50:26 +08:00
|
|
|
int res = REAL(getaddrinfo)(node, service, hints, out);
|
2013-05-28 22:34:37 +08:00
|
|
|
if (res == 0 && out) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, out, sizeof(*out));
|
2013-05-22 20:50:26 +08:00
|
|
|
struct __sanitizer_addrinfo *p = *out;
|
|
|
|
while (p) {
|
2013-05-28 22:34:37 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
|
2013-05-22 20:50:26 +08:00
|
|
|
if (p->ai_addr)
|
2013-05-29 20:33:31 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, p->ai_addrlen);
|
2013-05-22 20:50:26 +08:00
|
|
|
if (p->ai_canonname)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
|
|
|
|
REAL(strlen)(p->ai_canonname) + 1);
|
|
|
|
p = p->ai_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GETADDRINFO COMMON_INTERCEPT_FUNCTION(getaddrinfo);
|
2013-05-22 20:50:26 +08:00
|
|
|
#else
|
|
|
|
#define INIT_GETADDRINFO
|
|
|
|
#endif
|
|
|
|
|
2013-07-01 21:51:31 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETNAMEINFO
|
|
|
|
INTERCEPTOR(int, getnameinfo, void *sockaddr, unsigned salen, char *host,
|
|
|
|
unsigned hostlen, char *serv, unsigned servlen, int flags) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getnameinfo, sockaddr, salen, host, hostlen,
|
|
|
|
serv, servlen, flags);
|
|
|
|
// FIXME: consider adding READ_RANGE(sockaddr, salen)
|
|
|
|
// There is padding in in_addr that may make this too noisy
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-07-01 21:51:31 +08:00
|
|
|
int res =
|
|
|
|
REAL(getnameinfo)(sockaddr, salen, host, hostlen, serv, servlen, flags);
|
|
|
|
if (res == 0) {
|
|
|
|
if (host && hostlen)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, host, REAL(strlen)(host) + 1);
|
|
|
|
if (serv && servlen)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, serv, REAL(strlen)(serv) + 1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GETNAMEINFO COMMON_INTERCEPT_FUNCTION(getnameinfo);
|
2013-07-01 21:51:31 +08:00
|
|
|
#else
|
|
|
|
#define INIT_GETNAMEINFO
|
|
|
|
#endif
|
|
|
|
|
2013-05-22 21:46:22 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETSOCKNAME
|
|
|
|
INTERCEPTOR(int, getsockname, int sock_fd, void *addr, int *addrlen) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getsockname, sock_fd, addr, addrlen);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
|
|
|
|
int addrlen_in = *addrlen;
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-05-22 21:46:22 +08:00
|
|
|
int res = REAL(getsockname)(sock_fd, addr, addrlen);
|
|
|
|
if (res == 0) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addrlen_in, *addrlen));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GETSOCKNAME COMMON_INTERCEPT_FUNCTION(getsockname);
|
2013-05-22 21:46:22 +08:00
|
|
|
#else
|
|
|
|
#define INIT_GETSOCKNAME
|
|
|
|
#endif
|
2013-05-22 20:50:26 +08:00
|
|
|
|
2013-05-23 19:41:58 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETHOSTBYNAME || SANITIZER_INTERCEPT_GETHOSTBYNAME_R
|
2013-05-23 19:10:23 +08:00
|
|
|
static void write_hostent(void *ctx, struct __sanitizer_hostent *h) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h, sizeof(__sanitizer_hostent));
|
|
|
|
if (h->h_name)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h->h_name, REAL(strlen)(h->h_name) + 1);
|
|
|
|
char **p = h->h_aliases;
|
|
|
|
while (*p) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(
|
|
|
|
ctx, h->h_aliases, (p - h->h_aliases + 1) * sizeof(*h->h_aliases));
|
|
|
|
p = h->h_addr_list;
|
|
|
|
while (*p) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, h->h_length);
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(
|
|
|
|
ctx, h->h_addr_list, (p - h->h_addr_list + 1) * sizeof(*h->h_addr_list));
|
|
|
|
}
|
2013-05-23 19:41:58 +08:00
|
|
|
#endif
|
2013-05-23 19:10:23 +08:00
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_GETHOSTBYNAME
|
|
|
|
INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname, char *name) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname, name);
|
|
|
|
struct __sanitizer_hostent *res = REAL(gethostbyname)(name);
|
|
|
|
if (res) write_hostent(ctx, res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(struct __sanitizer_hostent *, gethostbyaddr, void *addr, int len,
|
|
|
|
int type) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr, addr, len, type);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
|
|
|
|
struct __sanitizer_hostent *res = REAL(gethostbyaddr)(addr, len, type);
|
|
|
|
if (res) write_hostent(ctx, res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-10-02 22:04:23 +08:00
|
|
|
INTERCEPTOR(struct __sanitizer_hostent *, gethostent, int fake) {
|
2013-05-23 19:10:23 +08:00
|
|
|
void *ctx;
|
2013-10-02 22:04:23 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, gethostent, fake);
|
|
|
|
struct __sanitizer_hostent *res = REAL(gethostent)(fake);
|
2013-05-23 19:10:23 +08:00
|
|
|
if (res) write_hostent(ctx, res);
|
|
|
|
return res;
|
|
|
|
}
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#define INIT_GETHOSTBYNAME \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(gethostent); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(gethostbyaddr); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(gethostbyname);
|
|
|
|
#else
|
|
|
|
#define INIT_GETHOSTBYNAME
|
|
|
|
#endif // SANITIZER_INTERCEPT_GETHOSTBYNAME
|
2013-05-23 19:10:23 +08:00
|
|
|
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETHOSTBYNAME2
|
2013-05-23 19:10:23 +08:00
|
|
|
INTERCEPTOR(struct __sanitizer_hostent *, gethostbyname2, char *name, int af) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2, name, af);
|
|
|
|
struct __sanitizer_hostent *res = REAL(gethostbyname2)(name, af);
|
|
|
|
if (res) write_hostent(ctx, res);
|
|
|
|
return res;
|
|
|
|
}
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#define INIT_GETHOSTBYNAME2 COMMON_INTERCEPT_FUNCTION(gethostbyname2);
|
2013-05-23 19:10:23 +08:00
|
|
|
#else
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
#define INIT_GETHOSTBYNAME2
|
|
|
|
#endif // SANITIZER_INTERCEPT_GETHOSTBYNAME2
|
2013-05-23 19:10:23 +08:00
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_GETHOSTBYNAME_R
|
2014-07-03 22:20:56 +08:00
|
|
|
INTERCEPTOR(int, gethostbyname_r, char *name, struct __sanitizer_hostent *ret,
|
|
|
|
char *buf, SIZE_T buflen, __sanitizer_hostent **result,
|
|
|
|
int *h_errnop) {
|
2013-05-23 19:10:23 +08:00
|
|
|
void *ctx;
|
2014-07-03 22:20:56 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname_r, name, ret, buf, buflen, result,
|
2013-05-23 19:10:23 +08:00
|
|
|
h_errnop);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-07-03 22:20:56 +08:00
|
|
|
int res = REAL(gethostbyname_r)(name, ret, buf, buflen, result, h_errnop);
|
2013-12-17 17:13:54 +08:00
|
|
|
if (result) {
|
2013-12-16 21:24:33 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
2013-12-17 17:13:54 +08:00
|
|
|
if (res == 0 && *result) write_hostent(ctx, *result);
|
2013-05-23 19:10:23 +08:00
|
|
|
}
|
2013-12-16 21:24:33 +08:00
|
|
|
if (h_errnop)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
|
2013-05-23 19:10:23 +08:00
|
|
|
return res;
|
|
|
|
}
|
2014-07-03 22:20:56 +08:00
|
|
|
#define INIT_GETHOSTBYNAME_R COMMON_INTERCEPT_FUNCTION(gethostbyname_r);
|
|
|
|
#else
|
|
|
|
#define INIT_GETHOSTBYNAME_R
|
|
|
|
#endif
|
2013-05-23 19:10:23 +08:00
|
|
|
|
2014-07-03 22:20:56 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETHOSTENT_R
|
|
|
|
INTERCEPTOR(int, gethostent_r, struct __sanitizer_hostent *ret, char *buf,
|
|
|
|
SIZE_T buflen, __sanitizer_hostent **result, int *h_errnop) {
|
2013-05-23 19:10:23 +08:00
|
|
|
void *ctx;
|
2014-07-03 22:20:56 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, gethostent_r, ret, buf, buflen, result,
|
|
|
|
h_errnop);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-07-03 22:20:56 +08:00
|
|
|
int res = REAL(gethostent_r)(ret, buf, buflen, result, h_errnop);
|
2013-12-17 17:13:54 +08:00
|
|
|
if (result) {
|
2013-12-16 21:24:33 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
2013-12-17 17:13:54 +08:00
|
|
|
if (res == 0 && *result) write_hostent(ctx, *result);
|
2013-05-23 19:10:23 +08:00
|
|
|
}
|
2013-12-16 21:24:33 +08:00
|
|
|
if (h_errnop)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
|
2013-05-23 19:10:23 +08:00
|
|
|
return res;
|
|
|
|
}
|
2014-07-03 22:20:56 +08:00
|
|
|
#define INIT_GETHOSTENT_R \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(gethostent_r);
|
|
|
|
#else
|
|
|
|
#define INIT_GETHOSTENT_R
|
|
|
|
#endif
|
2013-05-23 19:10:23 +08:00
|
|
|
|
2014-07-03 22:20:56 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETHOSTBYADDR_R
|
|
|
|
INTERCEPTOR(int, gethostbyaddr_r, void *addr, int len, int type,
|
|
|
|
struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
|
|
|
|
__sanitizer_hostent **result, int *h_errnop) {
|
2013-05-23 19:10:23 +08:00
|
|
|
void *ctx;
|
2014-07-03 22:20:56 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyaddr_r, addr, len, type, ret, buf,
|
|
|
|
buflen, result, h_errnop);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, len);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-07-03 22:20:56 +08:00
|
|
|
int res = REAL(gethostbyaddr_r)(addr, len, type, ret, buf, buflen, result,
|
|
|
|
h_errnop);
|
2013-12-17 17:13:54 +08:00
|
|
|
if (result) {
|
2013-12-16 21:24:33 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
2013-12-17 17:13:54 +08:00
|
|
|
if (res == 0 && *result) write_hostent(ctx, *result);
|
2013-05-23 19:10:23 +08:00
|
|
|
}
|
2013-12-16 21:24:33 +08:00
|
|
|
if (h_errnop)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
|
2013-05-23 19:10:23 +08:00
|
|
|
return res;
|
|
|
|
}
|
2014-07-03 22:20:56 +08:00
|
|
|
#define INIT_GETHOSTBYADDR_R \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(gethostbyaddr_r);
|
|
|
|
#else
|
|
|
|
#define INIT_GETHOSTBYADDR_R
|
|
|
|
#endif
|
2013-05-23 19:10:23 +08:00
|
|
|
|
2014-07-03 22:20:56 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETHOSTBYNAME2_R
|
2013-05-23 19:10:23 +08:00
|
|
|
INTERCEPTOR(int, gethostbyname2_r, char *name, int af,
|
|
|
|
struct __sanitizer_hostent *ret, char *buf, SIZE_T buflen,
|
|
|
|
__sanitizer_hostent **result, int *h_errnop) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, gethostbyname2_r, name, af, ret, buf, buflen,
|
|
|
|
result, h_errnop);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-05-23 19:10:23 +08:00
|
|
|
int res =
|
|
|
|
REAL(gethostbyname2_r)(name, af, ret, buf, buflen, result, h_errnop);
|
2013-12-17 17:13:54 +08:00
|
|
|
if (result) {
|
2013-12-16 21:24:33 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
2013-12-17 17:13:54 +08:00
|
|
|
if (res == 0 && *result) write_hostent(ctx, *result);
|
2013-05-23 19:10:23 +08:00
|
|
|
}
|
2013-12-16 21:24:33 +08:00
|
|
|
if (h_errnop)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, h_errnop, sizeof(*h_errnop));
|
2013-05-23 19:10:23 +08:00
|
|
|
return res;
|
|
|
|
}
|
2014-07-03 22:20:56 +08:00
|
|
|
#define INIT_GETHOSTBYNAME2_R \
|
2013-11-11 19:28:30 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION(gethostbyname2_r);
|
2013-05-23 19:10:23 +08:00
|
|
|
#else
|
2014-07-03 22:20:56 +08:00
|
|
|
#define INIT_GETHOSTBYNAME2_R
|
2013-05-23 19:10:23 +08:00
|
|
|
#endif
|
|
|
|
|
2013-05-23 19:38:08 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETSOCKOPT
|
|
|
|
INTERCEPTOR(int, getsockopt, int sockfd, int level, int optname, void *optval,
|
|
|
|
int *optlen) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getsockopt, sockfd, level, optname, optval,
|
|
|
|
optlen);
|
|
|
|
if (optlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, optlen, sizeof(*optlen));
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-05-23 19:38:08 +08:00
|
|
|
int res = REAL(getsockopt)(sockfd, level, optname, optval, optlen);
|
|
|
|
if (res == 0)
|
|
|
|
if (optval && optlen) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, optval, *optlen);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GETSOCKOPT COMMON_INTERCEPT_FUNCTION(getsockopt);
|
2013-05-23 19:38:08 +08:00
|
|
|
#else
|
|
|
|
#define INIT_GETSOCKOPT
|
|
|
|
#endif
|
|
|
|
|
2013-05-29 17:09:58 +08:00
|
|
|
#if SANITIZER_INTERCEPT_ACCEPT
|
|
|
|
INTERCEPTOR(int, accept, int fd, void *addr, unsigned *addrlen) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, accept, fd, addr, addrlen);
|
2014-06-16 16:32:02 +08:00
|
|
|
unsigned addrlen0 = 0;
|
2013-05-29 17:09:58 +08:00
|
|
|
if (addrlen) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
|
|
|
|
addrlen0 = *addrlen;
|
|
|
|
}
|
|
|
|
int fd2 = REAL(accept)(fd, addr, addrlen);
|
|
|
|
if (fd2 >= 0) {
|
2013-11-11 19:28:30 +08:00
|
|
|
if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
|
2013-05-29 17:09:58 +08:00
|
|
|
if (addr && addrlen)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
|
|
|
|
}
|
|
|
|
return fd2;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_ACCEPT COMMON_INTERCEPT_FUNCTION(accept);
|
2013-05-29 17:09:58 +08:00
|
|
|
#else
|
|
|
|
#define INIT_ACCEPT
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_ACCEPT4
|
|
|
|
INTERCEPTOR(int, accept4, int fd, void *addr, unsigned *addrlen, int f) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, accept4, fd, addr, addrlen, f);
|
2014-06-16 16:32:02 +08:00
|
|
|
unsigned addrlen0 = 0;
|
2013-05-29 17:09:58 +08:00
|
|
|
if (addrlen) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, addrlen, sizeof(*addrlen));
|
|
|
|
addrlen0 = *addrlen;
|
|
|
|
}
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-05-29 17:09:58 +08:00
|
|
|
int fd2 = REAL(accept4)(fd, addr, addrlen, f);
|
|
|
|
if (fd2 >= 0) {
|
2013-11-11 19:28:30 +08:00
|
|
|
if (fd >= 0) COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, fd2);
|
2013-05-29 17:09:58 +08:00
|
|
|
if (addr && addrlen)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(*addrlen, addrlen0));
|
|
|
|
}
|
|
|
|
return fd2;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_ACCEPT4 COMMON_INTERCEPT_FUNCTION(accept4);
|
2013-05-29 17:09:58 +08:00
|
|
|
#else
|
|
|
|
#define INIT_ACCEPT4
|
|
|
|
#endif
|
|
|
|
|
2013-05-29 18:03:11 +08:00
|
|
|
#if SANITIZER_INTERCEPT_MODF
|
|
|
|
INTERCEPTOR(double, modf, double x, double *iptr) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, modf, x, iptr);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-05-29 18:03:11 +08:00
|
|
|
double res = REAL(modf)(x, iptr);
|
|
|
|
if (iptr) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(float, modff, float x, float *iptr) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, modff, x, iptr);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-05-29 18:03:11 +08:00
|
|
|
float res = REAL(modff)(x, iptr);
|
|
|
|
if (iptr) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(long double, modfl, long double x, long double *iptr) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, modfl, x, iptr);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-05-29 18:03:11 +08:00
|
|
|
long double res = REAL(modfl)(x, iptr);
|
|
|
|
if (iptr) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iptr, sizeof(*iptr));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_MODF \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(modf); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(modff); \
|
2016-04-28 05:24:21 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(modfl);
|
2013-05-29 18:03:11 +08:00
|
|
|
#else
|
|
|
|
#define INIT_MODF
|
|
|
|
#endif
|
|
|
|
|
2018-01-04 07:32:15 +08:00
|
|
|
#if SANITIZER_INTERCEPT_RECVMSG || SANITIZER_INTERCEPT_RECVMMSG
|
2013-06-26 17:16:45 +08:00
|
|
|
static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
|
|
|
|
SSIZE_T maxlen) {
|
2013-05-29 19:30:00 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
|
2013-10-17 19:32:30 +08:00
|
|
|
if (msg->msg_name && msg->msg_namelen)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_name, msg->msg_namelen);
|
|
|
|
if (msg->msg_iov && msg->msg_iovlen)
|
2013-06-24 18:43:23 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_iov,
|
|
|
|
sizeof(*msg->msg_iov) * msg->msg_iovlen);
|
|
|
|
write_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
|
2013-10-17 19:32:30 +08:00
|
|
|
if (msg->msg_control && msg->msg_controllen)
|
2013-05-29 19:30:00 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
|
|
|
|
}
|
2018-01-04 07:32:15 +08:00
|
|
|
#endif
|
2013-05-29 19:30:00 +08:00
|
|
|
|
2018-01-04 07:32:15 +08:00
|
|
|
#if SANITIZER_INTERCEPT_RECVMSG
|
2013-05-29 19:30:00 +08:00
|
|
|
INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
|
|
|
|
int flags) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, recvmsg, fd, msg, flags);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-05-29 19:30:00 +08:00
|
|
|
SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
|
|
|
|
if (res >= 0) {
|
|
|
|
if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
2013-11-28 17:09:42 +08:00
|
|
|
if (msg) {
|
|
|
|
write_msghdr(ctx, msg, res);
|
|
|
|
COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg);
|
|
|
|
}
|
2013-05-29 19:30:00 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_RECVMSG COMMON_INTERCEPT_FUNCTION(recvmsg);
|
2013-05-29 19:30:00 +08:00
|
|
|
#else
|
|
|
|
#define INIT_RECVMSG
|
|
|
|
#endif
|
|
|
|
|
2018-01-04 07:32:15 +08:00
|
|
|
#if SANITIZER_INTERCEPT_RECVMMSG
|
|
|
|
INTERCEPTOR(int, recvmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
|
|
|
|
unsigned int vlen, int flags, void *timeout) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, recvmmsg, fd, msgvec, vlen, flags, timeout);
|
|
|
|
if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
|
|
|
|
int res = REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout);
|
|
|
|
if (res >= 0) {
|
|
|
|
if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
|
|
|
for (int i = 0; i < res; ++i) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
|
|
|
|
sizeof(msgvec[i].msg_len));
|
|
|
|
write_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
|
|
|
|
COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, &msgvec[i].msg_hdr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_RECVMMSG COMMON_INTERCEPT_FUNCTION(recvmmsg);
|
|
|
|
#else
|
|
|
|
#define INIT_RECVMMSG
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_SENDMSG || SANITIZER_INTERCEPT_SENDMMSG
|
2016-06-29 06:42:31 +08:00
|
|
|
static void read_msghdr_control(void *ctx, void *control, uptr controllen) {
|
|
|
|
const unsigned kCmsgDataOffset =
|
|
|
|
RoundUpTo(sizeof(__sanitizer_cmsghdr), sizeof(uptr));
|
|
|
|
|
|
|
|
char *p = (char *)control;
|
|
|
|
char *const control_end = p + controllen;
|
|
|
|
while (true) {
|
|
|
|
if (p + sizeof(__sanitizer_cmsghdr) > control_end) break;
|
|
|
|
__sanitizer_cmsghdr *cmsg = (__sanitizer_cmsghdr *)p;
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_len, sizeof(cmsg->cmsg_len));
|
|
|
|
|
|
|
|
if (p + RoundUpTo(cmsg->cmsg_len, sizeof(uptr)) > control_end) break;
|
|
|
|
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_level,
|
|
|
|
sizeof(cmsg->cmsg_level));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &cmsg->cmsg_type,
|
|
|
|
sizeof(cmsg->cmsg_type));
|
|
|
|
|
|
|
|
if (cmsg->cmsg_len > kCmsgDataOffset) {
|
|
|
|
char *data = p + kCmsgDataOffset;
|
|
|
|
unsigned data_len = cmsg->cmsg_len - kCmsgDataOffset;
|
|
|
|
if (data_len > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, data, data_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
p += RoundUpTo(cmsg->cmsg_len, sizeof(uptr));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-17 08:43:11 +08:00
|
|
|
static void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
|
|
|
|
SSIZE_T maxlen) {
|
2016-06-21 05:44:14 +08:00
|
|
|
#define R(f) \
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &msg->msg_##f, sizeof(msg->msg_##f))
|
|
|
|
R(name);
|
|
|
|
R(namelen);
|
|
|
|
R(iov);
|
|
|
|
R(iovlen);
|
|
|
|
R(control);
|
|
|
|
R(controllen);
|
|
|
|
R(flags);
|
|
|
|
#undef R
|
2016-06-17 08:43:11 +08:00
|
|
|
if (msg->msg_name && msg->msg_namelen)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_name, msg->msg_namelen);
|
|
|
|
if (msg->msg_iov && msg->msg_iovlen)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_iov,
|
|
|
|
sizeof(*msg->msg_iov) * msg->msg_iovlen);
|
|
|
|
read_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
|
|
|
|
if (msg->msg_control && msg->msg_controllen)
|
2016-06-29 06:42:31 +08:00
|
|
|
read_msghdr_control(ctx, msg->msg_control, msg->msg_controllen);
|
2016-06-17 08:43:11 +08:00
|
|
|
}
|
2018-01-04 07:32:15 +08:00
|
|
|
#endif
|
2016-06-17 08:43:11 +08:00
|
|
|
|
2018-01-04 07:32:15 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SENDMSG
|
2016-06-17 08:43:11 +08:00
|
|
|
INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
|
|
|
|
int flags) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sendmsg, fd, msg, flags);
|
|
|
|
if (fd >= 0) {
|
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
|
|
|
COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
|
|
|
}
|
|
|
|
SSIZE_T res = REAL(sendmsg)(fd, msg, flags);
|
2016-06-21 01:57:51 +08:00
|
|
|
if (common_flags()->intercept_send && res >= 0 && msg)
|
|
|
|
read_msghdr(ctx, msg, res);
|
2016-06-17 08:43:11 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_SENDMSG COMMON_INTERCEPT_FUNCTION(sendmsg);
|
|
|
|
#else
|
|
|
|
#define INIT_SENDMSG
|
|
|
|
#endif
|
|
|
|
|
2018-01-04 07:32:15 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SENDMMSG
|
|
|
|
INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
|
|
|
|
unsigned vlen, int flags) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sendmmsg, fd, msgvec, vlen, flags);
|
|
|
|
if (fd >= 0) {
|
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
|
|
|
COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
|
|
|
}
|
|
|
|
int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
|
|
|
|
if (res >= 0 && msgvec)
|
|
|
|
for (int i = 0; i < res; ++i) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
|
|
|
|
sizeof(msgvec[i].msg_len));
|
|
|
|
if (common_flags()->intercept_send)
|
|
|
|
read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg);
|
|
|
|
#else
|
|
|
|
#define INIT_SENDMMSG
|
|
|
|
#endif
|
|
|
|
|
2013-05-29 19:49:25 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETPEERNAME
|
|
|
|
INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getpeername, sockfd, addr, addrlen);
|
|
|
|
unsigned addr_sz;
|
|
|
|
if (addrlen) addr_sz = *addrlen;
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-05-29 19:49:25 +08:00
|
|
|
int res = REAL(getpeername)(sockfd, addr, addrlen);
|
|
|
|
if (!res && addr && addrlen)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, Min(addr_sz, *addrlen));
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GETPEERNAME COMMON_INTERCEPT_FUNCTION(getpeername);
|
2013-05-29 19:49:25 +08:00
|
|
|
#else
|
|
|
|
#define INIT_GETPEERNAME
|
|
|
|
#endif
|
|
|
|
|
2013-06-24 22:25:33 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SYSINFO
|
|
|
|
INTERCEPTOR(int, sysinfo, void *info) {
|
|
|
|
void *ctx;
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-06-24 22:25:33 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sysinfo, info);
|
|
|
|
int res = REAL(sysinfo)(info);
|
|
|
|
if (!res && info)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, struct_sysinfo_sz);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SYSINFO COMMON_INTERCEPT_FUNCTION(sysinfo);
|
2013-06-24 22:25:33 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SYSINFO
|
|
|
|
#endif
|
|
|
|
|
2013-06-26 23:00:53 +08:00
|
|
|
#if SANITIZER_INTERCEPT_READDIR
|
2015-01-21 16:54:01 +08:00
|
|
|
INTERCEPTOR(__sanitizer_dirent *, opendir, const char *path) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, opendir, path);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
|
|
|
__sanitizer_dirent *res = REAL(opendir)(path);
|
2015-09-30 02:23:36 +08:00
|
|
|
if (res)
|
2015-01-21 16:54:01 +08:00
|
|
|
COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-06-27 17:37:27 +08:00
|
|
|
INTERCEPTOR(__sanitizer_dirent *, readdir, void *dirp) {
|
2013-06-26 23:00:53 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, readdir, dirp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-06-27 17:37:27 +08:00
|
|
|
__sanitizer_dirent *res = REAL(readdir)(dirp);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
|
2013-06-26 23:00:53 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-06-28 20:13:31 +08:00
|
|
|
INTERCEPTOR(int, readdir_r, void *dirp, __sanitizer_dirent *entry,
|
|
|
|
__sanitizer_dirent **result) {
|
2013-06-26 23:00:53 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, readdir_r, dirp, entry, result);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-06-26 23:00:53 +08:00
|
|
|
int res = REAL(readdir_r)(dirp, entry, result);
|
|
|
|
if (!res) {
|
Fix a veritable conucopia of bugs in the readdir_r interceptors.
First, the reason I came here: I forgot to look at readdir64_r which had
the exact same bug as readdir_r. However, upon applying the same
quick-fix and testing it I discovered that it still didn't work at all.
As a consequence, I spent some time studying the code and thinking about
it and fixed several other problems.
Second, the code was checking for a null entry and result pointer, but
there is no indication that null pointers are viable here. Certainly,
the spec makes it extremely clear that there is no non-error case where
the implementation of readdir_r fails to dereference the 'result'
pointer and store NULL to it. Thus, our checking for a non-null 'result'
pointer before reflecting that write in the instrumentation was
trivially dead. Remove it.
Third, the interceptor was marking the write to the actual dirent struct
by looking at the entry pointer, but nothing in the spec requires that
the dirent struct written is actually written into the entry structure
provided. A threadlocal buffer would be just as conforming, and the spec
goes out of its way to say the pointer to the *actual* result dirent
struct is stored into *result, so *that* is where the interceptor should
reflect a write occuring. This also obviates the need to even consider
whether the 'entry' parameter is null.
Fourth, I got to the bottom of why nothing at all worked in readdir64_r
-- the interceptor structure for dirent64 was completely wrong in that
it was the same as dirent. I fixed this struct to be correct (64-bit
inode and 64-bit offset! just a 64-bit offset isn't enough!) and added
several missing tests for the size and layout of this struct.
llvm-svn: 186109
2013-07-12 02:51:40 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
|
|
|
if (*result)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
|
2013-06-26 23:00:53 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_READDIR \
|
2015-01-21 16:54:01 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION(opendir); \
|
2013-11-11 19:28:30 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION(readdir); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(readdir_r);
|
2013-06-26 23:00:53 +08:00
|
|
|
#else
|
|
|
|
#define INIT_READDIR
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_READDIR64
|
2013-06-27 17:37:27 +08:00
|
|
|
INTERCEPTOR(__sanitizer_dirent64 *, readdir64, void *dirp) {
|
2013-06-26 23:00:53 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, readdir64, dirp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-06-27 17:37:27 +08:00
|
|
|
__sanitizer_dirent64 *res = REAL(readdir64)(dirp);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, res->d_reclen);
|
2013-06-26 23:00:53 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-06-28 20:13:31 +08:00
|
|
|
INTERCEPTOR(int, readdir64_r, void *dirp, __sanitizer_dirent64 *entry,
|
|
|
|
__sanitizer_dirent64 **result) {
|
2013-06-26 23:00:53 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, readdir64_r, dirp, entry, result);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-06-26 23:00:53 +08:00
|
|
|
int res = REAL(readdir64_r)(dirp, entry, result);
|
|
|
|
if (!res) {
|
Fix a veritable conucopia of bugs in the readdir_r interceptors.
First, the reason I came here: I forgot to look at readdir64_r which had
the exact same bug as readdir_r. However, upon applying the same
quick-fix and testing it I discovered that it still didn't work at all.
As a consequence, I spent some time studying the code and thinking about
it and fixed several other problems.
Second, the code was checking for a null entry and result pointer, but
there is no indication that null pointers are viable here. Certainly,
the spec makes it extremely clear that there is no non-error case where
the implementation of readdir_r fails to dereference the 'result'
pointer and store NULL to it. Thus, our checking for a non-null 'result'
pointer before reflecting that write in the instrumentation was
trivially dead. Remove it.
Third, the interceptor was marking the write to the actual dirent struct
by looking at the entry pointer, but nothing in the spec requires that
the dirent struct written is actually written into the entry structure
provided. A threadlocal buffer would be just as conforming, and the spec
goes out of its way to say the pointer to the *actual* result dirent
struct is stored into *result, so *that* is where the interceptor should
reflect a write occuring. This also obviates the need to even consider
whether the 'entry' parameter is null.
Fourth, I got to the bottom of why nothing at all worked in readdir64_r
-- the interceptor structure for dirent64 was completely wrong in that
it was the same as dirent. I fixed this struct to be correct (64-bit
inode and 64-bit offset! just a 64-bit offset isn't enough!) and added
several missing tests for the size and layout of this struct.
llvm-svn: 186109
2013-07-12 02:51:40 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
|
|
|
if (*result)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *result, (*result)->d_reclen);
|
2013-06-26 23:00:53 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_READDIR64 \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(readdir64); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(readdir64_r);
|
2013-06-26 23:00:53 +08:00
|
|
|
#else
|
|
|
|
#define INIT_READDIR64
|
|
|
|
#endif
|
|
|
|
|
2013-06-28 19:02:43 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PTRACE
|
|
|
|
INTERCEPTOR(uptr, ptrace, int request, int pid, void *addr, void *data) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ptrace, request, pid, addr, data);
|
2015-10-27 02:55:04 +08:00
|
|
|
__sanitizer_iovec local_iovec;
|
2013-06-28 19:02:43 +08:00
|
|
|
|
|
|
|
if (data) {
|
|
|
|
if (request == ptrace_setregs)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_regs_struct_sz);
|
|
|
|
else if (request == ptrace_setfpregs)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpregs_struct_sz);
|
|
|
|
else if (request == ptrace_setfpxregs)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
|
2015-10-27 02:15:14 +08:00
|
|
|
else if (request == ptrace_setvfpregs)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
|
2013-06-28 19:02:43 +08:00
|
|
|
else if (request == ptrace_setsiginfo)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, data, siginfo_t_sz);
|
2015-10-27 02:55:04 +08:00
|
|
|
// Some kernel might zero the iovec::iov_base in case of invalid
|
|
|
|
// write access. In this case copy the invalid address for further
|
|
|
|
// inspection.
|
|
|
|
else if (request == ptrace_setregset || request == ptrace_getregset) {
|
|
|
|
__sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec, sizeof(*iovec));
|
|
|
|
local_iovec = *iovec;
|
|
|
|
if (request == ptrace_setregset)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, iovec->iov_base, iovec->iov_len);
|
2013-06-28 19:02:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-06-28 19:02:43 +08:00
|
|
|
uptr res = REAL(ptrace)(request, pid, addr, data);
|
|
|
|
|
|
|
|
if (!res && data) {
|
2014-06-16 21:49:13 +08:00
|
|
|
// Note that PEEK* requests assign different meaning to the return value.
|
2013-06-28 19:02:43 +08:00
|
|
|
// This function does not handle them (nor does it need to).
|
|
|
|
if (request == ptrace_getregs)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_regs_struct_sz);
|
|
|
|
else if (request == ptrace_getfpregs)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpregs_struct_sz);
|
|
|
|
else if (request == ptrace_getfpxregs)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_fpxregs_struct_sz);
|
2015-10-27 02:15:14 +08:00
|
|
|
else if (request == ptrace_getvfpregs)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, struct_user_vfpregs_struct_sz);
|
2013-06-28 19:02:43 +08:00
|
|
|
else if (request == ptrace_getsiginfo)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, siginfo_t_sz);
|
2014-06-16 21:49:13 +08:00
|
|
|
else if (request == ptrace_geteventmsg)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, data, sizeof(unsigned long));
|
2013-06-28 19:02:43 +08:00
|
|
|
else if (request == ptrace_getregset) {
|
2015-10-27 02:55:04 +08:00
|
|
|
__sanitizer_iovec *iovec = (__sanitizer_iovec*)data;
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, iovec, sizeof(*iovec));
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, local_iovec.iov_base,
|
|
|
|
local_iovec.iov_len);
|
2013-06-28 19:02:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PTRACE COMMON_INTERCEPT_FUNCTION(ptrace);
|
2013-06-28 19:02:43 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PTRACE
|
|
|
|
#endif
|
|
|
|
|
2013-07-02 17:23:45 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SETLOCALE
|
|
|
|
INTERCEPTOR(char *, setlocale, int category, char *locale) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, setlocale, category, locale);
|
|
|
|
if (locale)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, locale, REAL(strlen)(locale) + 1);
|
2013-07-02 21:34:44 +08:00
|
|
|
char *res = REAL(setlocale)(category, locale);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
|
2013-07-02 17:23:45 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SETLOCALE COMMON_INTERCEPT_FUNCTION(setlocale);
|
2013-07-02 17:23:45 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SETLOCALE
|
|
|
|
#endif
|
|
|
|
|
2013-07-02 21:34:44 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETCWD
|
|
|
|
INTERCEPTOR(char *, getcwd, char *buf, SIZE_T size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getcwd, buf, size);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-07-02 21:34:44 +08:00
|
|
|
char *res = REAL(getcwd)(buf, size);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
|
2013-07-02 21:34:44 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GETCWD COMMON_INTERCEPT_FUNCTION(getcwd);
|
2013-07-02 21:34:44 +08:00
|
|
|
#else
|
|
|
|
#define INIT_GETCWD
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_GET_CURRENT_DIR_NAME
|
2013-10-02 22:04:23 +08:00
|
|
|
INTERCEPTOR(char *, get_current_dir_name, int fake) {
|
2013-07-02 21:34:44 +08:00
|
|
|
void *ctx;
|
2013-10-02 22:04:23 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, get_current_dir_name, fake);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-02 22:04:23 +08:00
|
|
|
char *res = REAL(get_current_dir_name)(fake);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
|
2013-07-02 21:34:44 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GET_CURRENT_DIR_NAME \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(get_current_dir_name);
|
2013-07-02 21:34:44 +08:00
|
|
|
#else
|
|
|
|
#define INIT_GET_CURRENT_DIR_NAME
|
|
|
|
#endif
|
2013-06-26 23:00:53 +08:00
|
|
|
|
2015-04-07 02:00:26 +08:00
|
|
|
UNUSED static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) {
|
|
|
|
CHECK(endptr);
|
|
|
|
if (nptr == *endptr) {
|
|
|
|
// No digits were found at strtol call, we need to find out the last
|
|
|
|
// symbol accessed by strtoll on our own.
|
|
|
|
// We get this symbol by skipping leading blanks and optional +/- sign.
|
|
|
|
while (IsSpace(*nptr)) nptr++;
|
|
|
|
if (*nptr == '+' || *nptr == '-') nptr++;
|
|
|
|
*endptr = const_cast<char *>(nptr);
|
|
|
|
}
|
|
|
|
CHECK(*endptr >= nptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
UNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr,
|
|
|
|
char **endptr, char *real_endptr, int base) {
|
2015-09-30 02:23:36 +08:00
|
|
|
if (endptr) {
|
2015-04-07 02:00:26 +08:00
|
|
|
*endptr = real_endptr;
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, endptr, sizeof(*endptr));
|
|
|
|
}
|
|
|
|
// If base has unsupported value, strtol can exit with EINVAL
|
|
|
|
// without reading any characters. So do additional checks only
|
|
|
|
// if base is valid.
|
|
|
|
bool is_valid_base = (base == 0) || (2 <= base && base <= 36);
|
|
|
|
if (is_valid_base) {
|
|
|
|
FixRealStrtolEndptr(nptr, &real_endptr);
|
|
|
|
}
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, nptr, is_valid_base ?
|
|
|
|
(real_endptr - nptr) + 1 : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-04 21:19:41 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STRTOIMAX
|
|
|
|
INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2015-04-07 02:00:26 +08:00
|
|
|
char *real_endptr;
|
|
|
|
INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base);
|
|
|
|
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
|
2013-07-04 21:19:41 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(INTMAX_T, strtoumax, const char *nptr, char **endptr, int base) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2015-04-07 02:00:26 +08:00
|
|
|
char *real_endptr;
|
|
|
|
INTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base);
|
|
|
|
StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base);
|
2013-07-04 21:19:41 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_STRTOIMAX \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(strtoimax); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(strtoumax);
|
2013-07-04 21:19:41 +08:00
|
|
|
#else
|
|
|
|
#define INIT_STRTOIMAX
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_MBSTOWCS
|
|
|
|
INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, mbstowcs, dest, src, len);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-07-04 21:19:41 +08:00
|
|
|
SIZE_T res = REAL(mbstowcs)(dest, src, len);
|
2013-07-12 20:33:23 +08:00
|
|
|
if (res != (SIZE_T) - 1 && dest) {
|
2013-07-12 19:59:58 +08:00
|
|
|
SIZE_T write_cnt = res + (res < len);
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
|
|
|
|
}
|
2013-07-04 21:19:41 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(SIZE_T, mbsrtowcs, wchar_t *dest, const char **src, SIZE_T len,
|
|
|
|
void *ps) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, mbsrtowcs, dest, src, len, ps);
|
2013-07-12 20:33:23 +08:00
|
|
|
if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
|
|
|
|
if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
Fix a veritable conucopia of bugs in the readdir_r interceptors.
First, the reason I came here: I forgot to look at readdir64_r which had
the exact same bug as readdir_r. However, upon applying the same
quick-fix and testing it I discovered that it still didn't work at all.
As a consequence, I spent some time studying the code and thinking about
it and fixed several other problems.
Second, the code was checking for a null entry and result pointer, but
there is no indication that null pointers are viable here. Certainly,
the spec makes it extremely clear that there is no non-error case where
the implementation of readdir_r fails to dereference the 'result'
pointer and store NULL to it. Thus, our checking for a non-null 'result'
pointer before reflecting that write in the instrumentation was
trivially dead. Remove it.
Third, the interceptor was marking the write to the actual dirent struct
by looking at the entry pointer, but nothing in the spec requires that
the dirent struct written is actually written into the entry structure
provided. A threadlocal buffer would be just as conforming, and the spec
goes out of its way to say the pointer to the *actual* result dirent
struct is stored into *result, so *that* is where the interceptor should
reflect a write occuring. This also obviates the need to even consider
whether the 'entry' parameter is null.
Fourth, I got to the bottom of why nothing at all worked in readdir64_r
-- the interceptor structure for dirent64 was completely wrong in that
it was the same as dirent. I fixed this struct to be correct (64-bit
inode and 64-bit offset! just a 64-bit offset isn't enough!) and added
several missing tests for the size and layout of this struct.
llvm-svn: 186109
2013-07-12 02:51:40 +08:00
|
|
|
SIZE_T res = REAL(mbsrtowcs)(dest, src, len, ps);
|
2013-07-12 20:33:23 +08:00
|
|
|
if (res != (SIZE_T)(-1) && dest && src) {
|
|
|
|
// This function, and several others, may or may not write the terminating
|
|
|
|
// \0 character. They write it iff they clear *src.
|
|
|
|
SIZE_T write_cnt = res + !*src;
|
2013-07-12 19:59:58 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
|
|
|
|
}
|
2013-07-04 21:19:41 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_MBSTOWCS \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(mbstowcs); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(mbsrtowcs);
|
2013-07-04 21:19:41 +08:00
|
|
|
#else
|
|
|
|
#define INIT_MBSTOWCS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_MBSNRTOWCS
|
|
|
|
INTERCEPTOR(SIZE_T, mbsnrtowcs, wchar_t *dest, const char **src, SIZE_T nms,
|
|
|
|
SIZE_T len, void *ps) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, mbsnrtowcs, dest, src, nms, len, ps);
|
2013-07-12 20:33:23 +08:00
|
|
|
if (src) {
|
2013-07-04 21:19:41 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
|
2013-07-12 20:33:23 +08:00
|
|
|
if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
|
2013-07-04 21:19:41 +08:00
|
|
|
}
|
2013-07-12 20:33:23 +08:00
|
|
|
if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-07-04 21:19:41 +08:00
|
|
|
SIZE_T res = REAL(mbsnrtowcs)(dest, src, nms, len, ps);
|
2013-07-12 20:33:23 +08:00
|
|
|
if (res != (SIZE_T)(-1) && dest && src) {
|
|
|
|
SIZE_T write_cnt = res + !*src;
|
2013-07-12 19:59:58 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt * sizeof(wchar_t));
|
|
|
|
}
|
2013-07-04 21:19:41 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_MBSNRTOWCS COMMON_INTERCEPT_FUNCTION(mbsnrtowcs);
|
2013-07-04 21:19:41 +08:00
|
|
|
#else
|
|
|
|
#define INIT_MBSNRTOWCS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_WCSTOMBS
|
|
|
|
INTERCEPTOR(SIZE_T, wcstombs, char *dest, const wchar_t *src, SIZE_T len) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, wcstombs, dest, src, len);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-07-04 21:19:41 +08:00
|
|
|
SIZE_T res = REAL(wcstombs)(dest, src, len);
|
2013-07-12 20:33:23 +08:00
|
|
|
if (res != (SIZE_T) - 1 && dest) {
|
2013-07-12 19:59:58 +08:00
|
|
|
SIZE_T write_cnt = res + (res < len);
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
|
|
|
|
}
|
2013-07-04 21:19:41 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(SIZE_T, wcsrtombs, char *dest, const wchar_t **src, SIZE_T len,
|
|
|
|
void *ps) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, wcsrtombs, dest, src, len, ps);
|
2013-07-12 20:33:23 +08:00
|
|
|
if (src) COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
|
|
|
|
if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
Fix a veritable conucopia of bugs in the readdir_r interceptors.
First, the reason I came here: I forgot to look at readdir64_r which had
the exact same bug as readdir_r. However, upon applying the same
quick-fix and testing it I discovered that it still didn't work at all.
As a consequence, I spent some time studying the code and thinking about
it and fixed several other problems.
Second, the code was checking for a null entry and result pointer, but
there is no indication that null pointers are viable here. Certainly,
the spec makes it extremely clear that there is no non-error case where
the implementation of readdir_r fails to dereference the 'result'
pointer and store NULL to it. Thus, our checking for a non-null 'result'
pointer before reflecting that write in the instrumentation was
trivially dead. Remove it.
Third, the interceptor was marking the write to the actual dirent struct
by looking at the entry pointer, but nothing in the spec requires that
the dirent struct written is actually written into the entry structure
provided. A threadlocal buffer would be just as conforming, and the spec
goes out of its way to say the pointer to the *actual* result dirent
struct is stored into *result, so *that* is where the interceptor should
reflect a write occuring. This also obviates the need to even consider
whether the 'entry' parameter is null.
Fourth, I got to the bottom of why nothing at all worked in readdir64_r
-- the interceptor structure for dirent64 was completely wrong in that
it was the same as dirent. I fixed this struct to be correct (64-bit
inode and 64-bit offset! just a 64-bit offset isn't enough!) and added
several missing tests for the size and layout of this struct.
llvm-svn: 186109
2013-07-12 02:51:40 +08:00
|
|
|
SIZE_T res = REAL(wcsrtombs)(dest, src, len, ps);
|
2013-07-12 20:33:23 +08:00
|
|
|
if (res != (SIZE_T) - 1 && dest && src) {
|
|
|
|
SIZE_T write_cnt = res + !*src;
|
2013-07-12 19:59:58 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
|
|
|
|
}
|
2013-07-04 21:19:41 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_WCSTOMBS \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(wcstombs); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(wcsrtombs);
|
2013-07-04 21:19:41 +08:00
|
|
|
#else
|
|
|
|
#define INIT_WCSTOMBS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_WCSNRTOMBS
|
|
|
|
INTERCEPTOR(SIZE_T, wcsnrtombs, char *dest, const wchar_t **src, SIZE_T nms,
|
|
|
|
SIZE_T len, void *ps) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, wcsnrtombs, dest, src, nms, len, ps);
|
2013-07-12 20:33:23 +08:00
|
|
|
if (src) {
|
2013-07-04 21:19:41 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, sizeof(*src));
|
2013-07-12 20:33:23 +08:00
|
|
|
if (nms) COMMON_INTERCEPTOR_READ_RANGE(ctx, *src, nms);
|
2013-07-04 21:19:41 +08:00
|
|
|
}
|
2013-07-12 20:33:23 +08:00
|
|
|
if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-07-04 21:19:41 +08:00
|
|
|
SIZE_T res = REAL(wcsnrtombs)(dest, src, nms, len, ps);
|
2015-08-26 08:14:08 +08:00
|
|
|
if (res != ((SIZE_T)-1) && dest && src) {
|
2013-07-12 20:33:23 +08:00
|
|
|
SIZE_T write_cnt = res + !*src;
|
2013-07-12 19:59:58 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
|
|
|
|
}
|
2013-07-04 21:19:41 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_WCSNRTOMBS COMMON_INTERCEPT_FUNCTION(wcsnrtombs);
|
2013-07-04 21:19:41 +08:00
|
|
|
#else
|
|
|
|
#define INIT_WCSNRTOMBS
|
|
|
|
#endif
|
|
|
|
|
2015-08-26 08:14:08 +08:00
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_WCRTOMB
|
|
|
|
INTERCEPTOR(SIZE_T, wcrtomb, char *dest, wchar_t src, void *ps) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, wcrtomb, dest, src, ps);
|
|
|
|
if (ps) COMMON_INTERCEPTOR_READ_RANGE(ctx, ps, mbstate_t_sz);
|
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2015-08-26 08:14:08 +08:00
|
|
|
SIZE_T res = REAL(wcrtomb)(dest, src, ps);
|
|
|
|
if (res != ((SIZE_T)-1) && dest) {
|
|
|
|
SIZE_T write_cnt = res;
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dest, write_cnt);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_WCRTOMB COMMON_INTERCEPT_FUNCTION(wcrtomb);
|
|
|
|
#else
|
|
|
|
#define INIT_WCRTOMB
|
|
|
|
#endif
|
|
|
|
|
2013-07-04 22:03:31 +08:00
|
|
|
#if SANITIZER_INTERCEPT_TCGETATTR
|
|
|
|
INTERCEPTOR(int, tcgetattr, int fd, void *termios_p) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, tcgetattr, fd, termios_p);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-07-04 22:03:31 +08:00
|
|
|
int res = REAL(tcgetattr)(fd, termios_p);
|
|
|
|
if (!res && termios_p)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, termios_p, struct_termios_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_TCGETATTR COMMON_INTERCEPT_FUNCTION(tcgetattr);
|
2013-07-04 22:03:31 +08:00
|
|
|
#else
|
|
|
|
#define INIT_TCGETATTR
|
|
|
|
#endif
|
|
|
|
|
2013-07-09 17:53:37 +08:00
|
|
|
#if SANITIZER_INTERCEPT_REALPATH
|
|
|
|
INTERCEPTOR(char *, realpath, const char *path, char *resolved_path) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, realpath, path, resolved_path);
|
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
|
|
|
|
|
|
|
// Workaround a bug in glibc where dlsym(RTLD_NEXT, ...) returns the oldest
|
|
|
|
// version of a versioned symbol. For realpath(), this gives us something
|
|
|
|
// (called __old_realpath) that does not handle NULL in the second argument.
|
|
|
|
// Handle it as part of the interceptor.
|
2015-09-30 02:23:36 +08:00
|
|
|
char *allocated_path = nullptr;
|
2013-07-09 17:53:37 +08:00
|
|
|
if (!resolved_path)
|
|
|
|
allocated_path = resolved_path = (char *)WRAP(malloc)(path_max + 1);
|
|
|
|
|
|
|
|
char *res = REAL(realpath)(path, resolved_path);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (allocated_path && !res) WRAP(free)(allocated_path);
|
2013-07-09 17:53:37 +08:00
|
|
|
if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_REALPATH COMMON_INTERCEPT_FUNCTION(realpath);
|
2013-07-09 17:53:37 +08:00
|
|
|
#else
|
|
|
|
#define INIT_REALPATH
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_CANONICALIZE_FILE_NAME
|
|
|
|
INTERCEPTOR(char *, canonicalize_file_name, const char *path) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, canonicalize_file_name, path);
|
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
|
|
|
char *res = REAL(canonicalize_file_name)(path);
|
|
|
|
if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_CANONICALIZE_FILE_NAME \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(canonicalize_file_name);
|
2013-07-09 17:53:37 +08:00
|
|
|
#else
|
|
|
|
#define INIT_CANONICALIZE_FILE_NAME
|
|
|
|
#endif
|
|
|
|
|
2013-07-30 20:46:59 +08:00
|
|
|
#if SANITIZER_INTERCEPT_CONFSTR
|
|
|
|
INTERCEPTOR(SIZE_T, confstr, int name, char *buf, SIZE_T len) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, confstr, name, buf, len);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-07-30 20:46:59 +08:00
|
|
|
SIZE_T res = REAL(confstr)(name, buf, len);
|
|
|
|
if (buf && res)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, res < len ? res : len);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_CONFSTR COMMON_INTERCEPT_FUNCTION(confstr);
|
2013-07-30 20:46:59 +08:00
|
|
|
#else
|
|
|
|
#define INIT_CONFSTR
|
|
|
|
#endif
|
|
|
|
|
2013-08-07 17:10:16 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SCHED_GETAFFINITY
|
|
|
|
INTERCEPTOR(int, sched_getaffinity, int pid, SIZE_T cpusetsize, void *mask) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sched_getaffinity, pid, cpusetsize, mask);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-08-07 17:10:16 +08:00
|
|
|
int res = REAL(sched_getaffinity)(pid, cpusetsize, mask);
|
2013-11-11 19:28:30 +08:00
|
|
|
if (mask && !res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mask, cpusetsize);
|
2013-08-07 17:10:16 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SCHED_GETAFFINITY COMMON_INTERCEPT_FUNCTION(sched_getaffinity);
|
2013-08-07 17:10:16 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SCHED_GETAFFINITY
|
|
|
|
#endif
|
|
|
|
|
2015-01-22 22:03:07 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SCHED_GETPARAM
|
|
|
|
INTERCEPTOR(int, sched_getparam, int pid, void *param) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sched_getparam, pid, param);
|
|
|
|
int res = REAL(sched_getparam)(pid, param);
|
|
|
|
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, param, struct_sched_param_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_SCHED_GETPARAM COMMON_INTERCEPT_FUNCTION(sched_getparam);
|
|
|
|
#else
|
|
|
|
#define INIT_SCHED_GETPARAM
|
|
|
|
#endif
|
|
|
|
|
2013-08-08 19:44:05 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STRERROR
|
|
|
|
INTERCEPTOR(char *, strerror, int errnum) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strerror, errnum);
|
|
|
|
char *res = REAL(strerror)(errnum);
|
2014-03-06 21:26:09 +08:00
|
|
|
if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
|
2013-08-08 19:44:05 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_STRERROR COMMON_INTERCEPT_FUNCTION(strerror);
|
2013-08-08 19:44:05 +08:00
|
|
|
#else
|
|
|
|
#define INIT_STRERROR
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_STRERROR_R
|
2017-03-09 06:51:03 +08:00
|
|
|
// There are 2 versions of strerror_r:
|
|
|
|
// * POSIX version returns 0 on success, negative error code on failure,
|
|
|
|
// writes message to buf.
|
|
|
|
// * GNU version returns message pointer, which points to either buf or some
|
|
|
|
// static storage.
|
|
|
|
#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || \
|
2017-12-09 08:35:44 +08:00
|
|
|
SANITIZER_MAC || SANITIZER_ANDROID || SANITIZER_NETBSD
|
2017-03-09 06:51:03 +08:00
|
|
|
// POSIX version. Spec is not clear on whether buf is NULL-terminated.
|
|
|
|
// At least on OSX, buf contents are valid even when the call fails.
|
|
|
|
INTERCEPTOR(int, strerror_r, int errnum, char *buf, SIZE_T buflen) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
|
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
|
|
|
int res = REAL(strerror_r)(errnum, buf, buflen);
|
|
|
|
|
|
|
|
SIZE_T sz = internal_strnlen(buf, buflen);
|
|
|
|
if (sz < buflen) ++sz;
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
// GNU version.
|
2013-08-08 19:44:05 +08:00
|
|
|
INTERCEPTOR(char *, strerror_r, int errnum, char *buf, SIZE_T buflen) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, strerror_r, errnum, buf, buflen);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-08-08 19:44:05 +08:00
|
|
|
char *res = REAL(strerror_r)(errnum, buf, buflen);
|
2017-06-07 09:53:38 +08:00
|
|
|
if (res == buf)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
|
|
|
|
else
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
|
2013-08-08 19:44:05 +08:00
|
|
|
return res;
|
|
|
|
}
|
2017-03-09 06:51:03 +08:00
|
|
|
#endif //(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE ||
|
|
|
|
//SANITIZER_MAC
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_STRERROR_R COMMON_INTERCEPT_FUNCTION(strerror_r);
|
2013-08-08 19:44:05 +08:00
|
|
|
#else
|
|
|
|
#define INIT_STRERROR_R
|
|
|
|
#endif
|
|
|
|
|
2013-11-27 20:29:10 +08:00
|
|
|
#if SANITIZER_INTERCEPT_XPG_STRERROR_R
|
|
|
|
INTERCEPTOR(int, __xpg_strerror_r, int errnum, char *buf, SIZE_T buflen) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __xpg_strerror_r, errnum, buf, buflen);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-11-27 20:29:10 +08:00
|
|
|
int res = REAL(__xpg_strerror_r)(errnum, buf, buflen);
|
|
|
|
// This version always returns a null-terminated string.
|
|
|
|
if (buf && buflen)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_XPG_STRERROR_R COMMON_INTERCEPT_FUNCTION(__xpg_strerror_r);
|
|
|
|
#else
|
|
|
|
#define INIT_XPG_STRERROR_R
|
|
|
|
#endif
|
|
|
|
|
2013-08-08 21:57:15 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SCANDIR
|
|
|
|
typedef int (*scandir_filter_f)(const struct __sanitizer_dirent *);
|
|
|
|
typedef int (*scandir_compar_f)(const struct __sanitizer_dirent **,
|
|
|
|
const struct __sanitizer_dirent **);
|
|
|
|
|
|
|
|
static THREADLOCAL scandir_filter_f scandir_filter;
|
|
|
|
static THREADLOCAL scandir_compar_f scandir_compar;
|
|
|
|
|
|
|
|
static int wrapped_scandir_filter(const struct __sanitizer_dirent *dir) {
|
2014-03-06 21:26:09 +08:00
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
|
2014-11-18 18:33:15 +08:00
|
|
|
return scandir_filter(dir);
|
2013-08-08 21:57:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int wrapped_scandir_compar(const struct __sanitizer_dirent **a,
|
|
|
|
const struct __sanitizer_dirent **b) {
|
2014-03-06 21:26:09 +08:00
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
|
2014-11-18 18:33:15 +08:00
|
|
|
return scandir_compar(a, b);
|
2013-08-08 21:57:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, scandir, char *dirp, __sanitizer_dirent ***namelist,
|
|
|
|
scandir_filter_f filter, scandir_compar_f compar) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, scandir, dirp, namelist, filter, compar);
|
|
|
|
if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
|
|
|
|
scandir_filter = filter;
|
|
|
|
scandir_compar = compar;
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2015-09-30 02:23:36 +08:00
|
|
|
int res = REAL(scandir)(dirp, namelist,
|
|
|
|
filter ? wrapped_scandir_filter : nullptr,
|
|
|
|
compar ? wrapped_scandir_compar : nullptr);
|
|
|
|
scandir_filter = nullptr;
|
|
|
|
scandir_compar = nullptr;
|
2013-08-08 21:57:15 +08:00
|
|
|
if (namelist && res > 0) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
|
|
|
|
for (int i = 0; i < res; ++i)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
|
|
|
|
(*namelist)[i]->d_reclen);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SCANDIR COMMON_INTERCEPT_FUNCTION(scandir);
|
2013-08-08 21:57:15 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SCANDIR
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_SCANDIR64
|
|
|
|
typedef int (*scandir64_filter_f)(const struct __sanitizer_dirent64 *);
|
|
|
|
typedef int (*scandir64_compar_f)(const struct __sanitizer_dirent64 **,
|
|
|
|
const struct __sanitizer_dirent64 **);
|
|
|
|
|
|
|
|
static THREADLOCAL scandir64_filter_f scandir64_filter;
|
|
|
|
static THREADLOCAL scandir64_compar_f scandir64_compar;
|
|
|
|
|
|
|
|
static int wrapped_scandir64_filter(const struct __sanitizer_dirent64 *dir) {
|
2014-03-06 21:26:09 +08:00
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(dir, dir->d_reclen);
|
2014-11-18 18:33:15 +08:00
|
|
|
return scandir64_filter(dir);
|
2013-08-08 21:57:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int wrapped_scandir64_compar(const struct __sanitizer_dirent64 **a,
|
|
|
|
const struct __sanitizer_dirent64 **b) {
|
2014-03-06 21:26:09 +08:00
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(2);
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(a, sizeof(*a));
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(*a, (*a)->d_reclen);
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(b, sizeof(*b));
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(*b, (*b)->d_reclen);
|
2014-11-18 18:33:15 +08:00
|
|
|
return scandir64_compar(a, b);
|
2013-08-08 21:57:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, scandir64, char *dirp, __sanitizer_dirent64 ***namelist,
|
|
|
|
scandir64_filter_f filter, scandir64_compar_f compar) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, scandir64, dirp, namelist, filter, compar);
|
|
|
|
if (dirp) COMMON_INTERCEPTOR_READ_RANGE(ctx, dirp, REAL(strlen)(dirp) + 1);
|
|
|
|
scandir64_filter = filter;
|
|
|
|
scandir64_compar = compar;
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-08-08 21:57:15 +08:00
|
|
|
int res =
|
2015-09-30 02:23:36 +08:00
|
|
|
REAL(scandir64)(dirp, namelist,
|
|
|
|
filter ? wrapped_scandir64_filter : nullptr,
|
|
|
|
compar ? wrapped_scandir64_compar : nullptr);
|
|
|
|
scandir64_filter = nullptr;
|
|
|
|
scandir64_compar = nullptr;
|
2013-08-08 21:57:15 +08:00
|
|
|
if (namelist && res > 0) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, namelist, sizeof(*namelist));
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *namelist, sizeof(**namelist) * res);
|
|
|
|
for (int i = 0; i < res; ++i)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (*namelist)[i],
|
|
|
|
(*namelist)[i]->d_reclen);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SCANDIR64 COMMON_INTERCEPT_FUNCTION(scandir64);
|
2013-08-08 21:57:15 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SCANDIR64
|
|
|
|
#endif
|
|
|
|
|
2013-08-12 19:01:40 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETGROUPS
|
|
|
|
INTERCEPTOR(int, getgroups, int size, u32 *lst) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getgroups, size, lst);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-08-12 19:01:40 +08:00
|
|
|
int res = REAL(getgroups)(size, lst);
|
2017-03-30 06:59:28 +08:00
|
|
|
if (res >= 0 && lst && size > 0)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lst, res * sizeof(*lst));
|
2013-08-12 19:01:40 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GETGROUPS COMMON_INTERCEPT_FUNCTION(getgroups);
|
2013-08-12 19:01:40 +08:00
|
|
|
#else
|
|
|
|
#define INIT_GETGROUPS
|
|
|
|
#endif
|
|
|
|
|
2013-08-12 21:19:53 +08:00
|
|
|
#if SANITIZER_INTERCEPT_POLL
|
|
|
|
static void read_pollfd(void *ctx, __sanitizer_pollfd *fds,
|
|
|
|
__sanitizer_nfds_t nfds) {
|
|
|
|
for (unsigned i = 0; i < nfds; ++i) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].fd, sizeof(fds[i].fd));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, &fds[i].events, sizeof(fds[i].events));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_pollfd(void *ctx, __sanitizer_pollfd *fds,
|
|
|
|
__sanitizer_nfds_t nfds) {
|
|
|
|
for (unsigned i = 0; i < nfds; ++i)
|
2013-08-23 15:43:56 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &fds[i].revents,
|
|
|
|
sizeof(fds[i].revents));
|
2013-08-12 21:19:53 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, poll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
|
|
|
|
int timeout) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, poll, fds, nfds, timeout);
|
|
|
|
if (fds && nfds) read_pollfd(ctx, fds, nfds);
|
|
|
|
int res = COMMON_INTERCEPTOR_BLOCK_REAL(poll)(fds, nfds, timeout);
|
|
|
|
if (fds && nfds) write_pollfd(ctx, fds, nfds);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_POLL COMMON_INTERCEPT_FUNCTION(poll);
|
2013-08-12 21:19:53 +08:00
|
|
|
#else
|
|
|
|
#define INIT_POLL
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PPOLL
|
|
|
|
INTERCEPTOR(int, ppoll, __sanitizer_pollfd *fds, __sanitizer_nfds_t nfds,
|
2013-08-27 19:10:04 +08:00
|
|
|
void *timeout_ts, __sanitizer_sigset_t *sigmask) {
|
2013-08-12 21:19:53 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ppoll, fds, nfds, timeout_ts, sigmask);
|
|
|
|
if (fds && nfds) read_pollfd(ctx, fds, nfds);
|
|
|
|
if (timeout_ts)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout_ts, struct_timespec_sz);
|
2017-09-06 05:08:56 +08:00
|
|
|
if (sigmask) COMMON_INTERCEPTOR_READ_RANGE(ctx, sigmask, sizeof(*sigmask));
|
2013-08-12 21:19:53 +08:00
|
|
|
int res =
|
|
|
|
COMMON_INTERCEPTOR_BLOCK_REAL(ppoll)(fds, nfds, timeout_ts, sigmask);
|
|
|
|
if (fds && nfds) write_pollfd(ctx, fds, nfds);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PPOLL COMMON_INTERCEPT_FUNCTION(ppoll);
|
2013-08-12 21:19:53 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PPOLL
|
|
|
|
#endif
|
|
|
|
|
2013-09-24 22:38:22 +08:00
|
|
|
#if SANITIZER_INTERCEPT_WORDEXP
|
|
|
|
INTERCEPTOR(int, wordexp, char *s, __sanitizer_wordexp_t *p, int flags) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, wordexp, s, p, flags);
|
|
|
|
if (s) COMMON_INTERCEPTOR_READ_RANGE(ctx, s, REAL(strlen)(s) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-09-24 22:38:22 +08:00
|
|
|
int res = REAL(wordexp)(s, p, flags);
|
|
|
|
if (!res && p) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
|
|
|
|
if (p->we_wordc)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->we_wordv,
|
|
|
|
sizeof(*p->we_wordv) * p->we_wordc);
|
|
|
|
for (uptr i = 0; i < p->we_wordc; ++i) {
|
|
|
|
char *w = p->we_wordv[i];
|
|
|
|
if (w) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, w, REAL(strlen)(w) + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_WORDEXP COMMON_INTERCEPT_FUNCTION(wordexp);
|
2013-09-24 22:38:22 +08:00
|
|
|
#else
|
|
|
|
#define INIT_WORDEXP
|
|
|
|
#endif
|
|
|
|
|
2013-09-25 22:47:43 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SIGWAIT
|
|
|
|
INTERCEPTOR(int, sigwait, __sanitizer_sigset_t *set, int *sig) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sigwait, set, sig);
|
2017-09-06 05:08:56 +08:00
|
|
|
if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-09-25 22:47:43 +08:00
|
|
|
int res = REAL(sigwait)(set, sig);
|
|
|
|
if (!res && sig) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sig, sizeof(*sig));
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SIGWAIT COMMON_INTERCEPT_FUNCTION(sigwait);
|
2013-09-25 22:47:43 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SIGWAIT
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_SIGWAITINFO
|
|
|
|
INTERCEPTOR(int, sigwaitinfo, __sanitizer_sigset_t *set, void *info) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sigwaitinfo, set, info);
|
2017-09-06 05:08:56 +08:00
|
|
|
if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-09-25 22:47:43 +08:00
|
|
|
int res = REAL(sigwaitinfo)(set, info);
|
|
|
|
if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SIGWAITINFO COMMON_INTERCEPT_FUNCTION(sigwaitinfo);
|
2013-09-25 22:47:43 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SIGWAITINFO
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_SIGTIMEDWAIT
|
|
|
|
INTERCEPTOR(int, sigtimedwait, __sanitizer_sigset_t *set, void *info,
|
|
|
|
void *timeout) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sigtimedwait, set, info, timeout);
|
|
|
|
if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
|
2017-09-06 05:08:56 +08:00
|
|
|
if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-09-25 22:47:43 +08:00
|
|
|
int res = REAL(sigtimedwait)(set, info, timeout);
|
|
|
|
if (res > 0 && info) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, info, siginfo_t_sz);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SIGTIMEDWAIT COMMON_INTERCEPT_FUNCTION(sigtimedwait);
|
2013-09-25 22:47:43 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SIGTIMEDWAIT
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_SIGSETOPS
|
|
|
|
INTERCEPTOR(int, sigemptyset, __sanitizer_sigset_t *set) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sigemptyset, set);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-09-25 22:47:43 +08:00
|
|
|
int res = REAL(sigemptyset)(set);
|
|
|
|
if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sigfillset, set);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-09-25 22:47:43 +08:00
|
|
|
int res = REAL(sigfillset)(set);
|
|
|
|
if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SIGSETOPS \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(sigemptyset); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(sigfillset);
|
2013-09-25 22:47:43 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SIGSETOPS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_SIGPENDING
|
|
|
|
INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sigpending, set);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-09-25 22:47:43 +08:00
|
|
|
int res = REAL(sigpending)(set);
|
|
|
|
if (!res && set) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, set, sizeof(*set));
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SIGPENDING COMMON_INTERCEPT_FUNCTION(sigpending);
|
2013-09-25 22:47:43 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SIGPENDING
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_SIGPROCMASK
|
|
|
|
INTERCEPTOR(int, sigprocmask, int how, __sanitizer_sigset_t *set,
|
|
|
|
__sanitizer_sigset_t *oldset) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sigprocmask, how, set, oldset);
|
2017-09-06 05:08:56 +08:00
|
|
|
if (set) COMMON_INTERCEPTOR_READ_RANGE(ctx, set, sizeof(*set));
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-09-25 22:47:43 +08:00
|
|
|
int res = REAL(sigprocmask)(how, set, oldset);
|
|
|
|
if (!res && oldset)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldset, sizeof(*oldset));
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SIGPROCMASK COMMON_INTERCEPT_FUNCTION(sigprocmask);
|
2013-09-25 22:47:43 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SIGPROCMASK
|
|
|
|
#endif
|
|
|
|
|
2013-09-27 20:40:23 +08:00
|
|
|
#if SANITIZER_INTERCEPT_BACKTRACE
|
|
|
|
INTERCEPTOR(int, backtrace, void **buffer, int size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, backtrace, buffer, size);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-09-27 20:40:23 +08:00
|
|
|
int res = REAL(backtrace)(buffer, size);
|
|
|
|
if (res && buffer)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buffer, res * sizeof(*buffer));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(char **, backtrace_symbols, void **buffer, int size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, backtrace_symbols, buffer, size);
|
|
|
|
if (buffer && size)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, buffer, size * sizeof(*buffer));
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-11-11 19:28:30 +08:00
|
|
|
char **res = REAL(backtrace_symbols)(buffer, size);
|
2013-09-27 20:40:23 +08:00
|
|
|
if (res && size) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, size * sizeof(*res));
|
|
|
|
for (int i = 0; i < size; ++i)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res[i], REAL(strlen(res[i])) + 1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_BACKTRACE \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(backtrace); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(backtrace_symbols);
|
2013-09-27 20:40:23 +08:00
|
|
|
#else
|
|
|
|
#define INIT_BACKTRACE
|
|
|
|
#endif
|
|
|
|
|
2013-10-03 23:22:29 +08:00
|
|
|
#if SANITIZER_INTERCEPT__EXIT
|
|
|
|
INTERCEPTOR(void, _exit, int status) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, _exit, status);
|
2016-01-14 20:24:37 +08:00
|
|
|
COMMON_INTERCEPTOR_USER_CALLBACK_START();
|
2013-10-03 23:22:29 +08:00
|
|
|
int status1 = COMMON_INTERCEPTOR_ON_EXIT(ctx);
|
2016-01-14 20:24:37 +08:00
|
|
|
COMMON_INTERCEPTOR_USER_CALLBACK_END();
|
2013-11-11 19:28:30 +08:00
|
|
|
if (status == 0) status = status1;
|
2013-10-03 23:22:29 +08:00
|
|
|
REAL(_exit)(status);
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT__EXIT COMMON_INTERCEPT_FUNCTION(_exit);
|
2013-10-03 23:22:29 +08:00
|
|
|
#else
|
|
|
|
#define INIT__EXIT
|
|
|
|
#endif
|
|
|
|
|
2013-10-16 16:20:31 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PHTREAD_MUTEX
|
|
|
|
INTERCEPTOR(int, pthread_mutex_lock, void *m) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_lock, m);
|
2017-03-26 23:27:04 +08:00
|
|
|
COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m);
|
2013-10-16 16:20:31 +08:00
|
|
|
int res = REAL(pthread_mutex_lock)(m);
|
2013-11-16 00:58:12 +08:00
|
|
|
if (res == errno_EOWNERDEAD)
|
|
|
|
COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
|
|
|
|
if (res == 0 || res == errno_EOWNERDEAD)
|
2017-03-26 23:27:04 +08:00
|
|
|
COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m);
|
2016-03-16 23:39:20 +08:00
|
|
|
if (res == errno_EINVAL)
|
|
|
|
COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
|
2013-10-16 16:20:31 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, pthread_mutex_unlock, void *m) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_unlock, m);
|
|
|
|
COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
|
2016-03-16 23:39:20 +08:00
|
|
|
int res = REAL(pthread_mutex_unlock)(m);
|
|
|
|
if (res == errno_EINVAL)
|
|
|
|
COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
|
|
|
|
return res;
|
2013-10-16 16:20:31 +08:00
|
|
|
}
|
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PTHREAD_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(pthread_mutex_lock)
|
|
|
|
#define INIT_PTHREAD_MUTEX_UNLOCK \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_mutex_unlock)
|
2013-10-16 16:20:31 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_MUTEX_LOCK
|
|
|
|
#define INIT_PTHREAD_MUTEX_UNLOCK
|
|
|
|
#endif
|
|
|
|
|
Handle NetBSD specific indirection of libpthread functions
Summary:
Correct handling of three libpthread(3) functions on NetBSD:
- pthread_mutex_lock(3),
- pthread_mutex_unlock(3),
- pthread_setcancelstate(3).
Code out of the libpthread(3) context uses the libc symbols:
- __libc_mutex_lock,
- __libc_mutex_unlock,
- __libc_thr_setcancelstate.
The threading library (libpthread(3)) defines strong aliases:
- __strong_alias(__libc_mutex_lock,pthread_mutex_lock)
- __strong_alias(__libc_mutex_unlock,pthread_mutex_unlock)
- __strong_alias(__libc_thr_setcancelstate,pthread_setcancelstate)
This caused that these functions were invisible to sanitizers on NetBSD.
Intercept the libc-specific ones and add them as NetBSD-specific aliases
for the common pthread(3) ones.
NetBSD needs to intercept both functions, as the regularly named ones
are used internally in libpthread(3).
Sponsored by <The NetBSD Foundation>
Reviewers: joerg, dvyukov, vitalybuka
Reviewed By: dvyukov
Subscribers: llvm-commits, kubamracek, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40241
llvm-svn: 318646
2017-11-20 20:21:11 +08:00
|
|
|
#if SANITIZER_NETBSD
|
2017-11-20 23:39:30 +08:00
|
|
|
INTERCEPTOR(int, __libc_mutex_lock, void *m) \
|
Handle NetBSD specific indirection of libpthread functions
Summary:
Correct handling of three libpthread(3) functions on NetBSD:
- pthread_mutex_lock(3),
- pthread_mutex_unlock(3),
- pthread_setcancelstate(3).
Code out of the libpthread(3) context uses the libc symbols:
- __libc_mutex_lock,
- __libc_mutex_unlock,
- __libc_thr_setcancelstate.
The threading library (libpthread(3)) defines strong aliases:
- __strong_alias(__libc_mutex_lock,pthread_mutex_lock)
- __strong_alias(__libc_mutex_unlock,pthread_mutex_unlock)
- __strong_alias(__libc_thr_setcancelstate,pthread_setcancelstate)
This caused that these functions were invisible to sanitizers on NetBSD.
Intercept the libc-specific ones and add them as NetBSD-specific aliases
for the common pthread(3) ones.
NetBSD needs to intercept both functions, as the regularly named ones
are used internally in libpthread(3).
Sponsored by <The NetBSD Foundation>
Reviewers: joerg, dvyukov, vitalybuka
Reviewed By: dvyukov
Subscribers: llvm-commits, kubamracek, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40241
llvm-svn: 318646
2017-11-20 20:21:11 +08:00
|
|
|
ALIAS(WRAPPER_NAME(pthread_mutex_lock));
|
2017-11-20 23:39:30 +08:00
|
|
|
INTERCEPTOR(int, __libc_mutex_unlock, void *m) \
|
Handle NetBSD specific indirection of libpthread functions
Summary:
Correct handling of three libpthread(3) functions on NetBSD:
- pthread_mutex_lock(3),
- pthread_mutex_unlock(3),
- pthread_setcancelstate(3).
Code out of the libpthread(3) context uses the libc symbols:
- __libc_mutex_lock,
- __libc_mutex_unlock,
- __libc_thr_setcancelstate.
The threading library (libpthread(3)) defines strong aliases:
- __strong_alias(__libc_mutex_lock,pthread_mutex_lock)
- __strong_alias(__libc_mutex_unlock,pthread_mutex_unlock)
- __strong_alias(__libc_thr_setcancelstate,pthread_setcancelstate)
This caused that these functions were invisible to sanitizers on NetBSD.
Intercept the libc-specific ones and add them as NetBSD-specific aliases
for the common pthread(3) ones.
NetBSD needs to intercept both functions, as the regularly named ones
are used internally in libpthread(3).
Sponsored by <The NetBSD Foundation>
Reviewers: joerg, dvyukov, vitalybuka
Reviewed By: dvyukov
Subscribers: llvm-commits, kubamracek, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40241
llvm-svn: 318646
2017-11-20 20:21:11 +08:00
|
|
|
ALIAS(WRAPPER_NAME(pthread_mutex_unlock));
|
2017-11-20 23:39:30 +08:00
|
|
|
INTERCEPTOR(int, __libc_thr_setcancelstate, int state, int *oldstate) \
|
Handle NetBSD specific indirection of libpthread functions
Summary:
Correct handling of three libpthread(3) functions on NetBSD:
- pthread_mutex_lock(3),
- pthread_mutex_unlock(3),
- pthread_setcancelstate(3).
Code out of the libpthread(3) context uses the libc symbols:
- __libc_mutex_lock,
- __libc_mutex_unlock,
- __libc_thr_setcancelstate.
The threading library (libpthread(3)) defines strong aliases:
- __strong_alias(__libc_mutex_lock,pthread_mutex_lock)
- __strong_alias(__libc_mutex_unlock,pthread_mutex_unlock)
- __strong_alias(__libc_thr_setcancelstate,pthread_setcancelstate)
This caused that these functions were invisible to sanitizers on NetBSD.
Intercept the libc-specific ones and add them as NetBSD-specific aliases
for the common pthread(3) ones.
NetBSD needs to intercept both functions, as the regularly named ones
are used internally in libpthread(3).
Sponsored by <The NetBSD Foundation>
Reviewers: joerg, dvyukov, vitalybuka
Reviewed By: dvyukov
Subscribers: llvm-commits, kubamracek, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40241
llvm-svn: 318646
2017-11-20 20:21:11 +08:00
|
|
|
ALIAS(WRAPPER_NAME(pthread_setcancelstate));
|
|
|
|
#endif
|
|
|
|
|
2013-10-18 17:41:43 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETMNTENT || SANITIZER_INTERCEPT_GETMNTENT_R
|
|
|
|
static void write_mntent(void *ctx, __sanitizer_mntent *mnt) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt, sizeof(*mnt));
|
|
|
|
if (mnt->mnt_fsname)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_fsname,
|
|
|
|
REAL(strlen)(mnt->mnt_fsname) + 1);
|
|
|
|
if (mnt->mnt_dir)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_dir,
|
|
|
|
REAL(strlen)(mnt->mnt_dir) + 1);
|
|
|
|
if (mnt->mnt_type)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_type,
|
|
|
|
REAL(strlen)(mnt->mnt_type) + 1);
|
|
|
|
if (mnt->mnt_opts)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, mnt->mnt_opts,
|
|
|
|
REAL(strlen)(mnt->mnt_opts) + 1);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_GETMNTENT
|
|
|
|
INTERCEPTOR(__sanitizer_mntent *, getmntent, void *fp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getmntent, fp);
|
|
|
|
__sanitizer_mntent *res = REAL(getmntent)(fp);
|
|
|
|
if (res) write_mntent(ctx, res);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GETMNTENT COMMON_INTERCEPT_FUNCTION(getmntent);
|
2013-10-18 17:41:43 +08:00
|
|
|
#else
|
|
|
|
#define INIT_GETMNTENT
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_GETMNTENT_R
|
|
|
|
INTERCEPTOR(__sanitizer_mntent *, getmntent_r, void *fp,
|
|
|
|
__sanitizer_mntent *mntbuf, char *buf, int buflen) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getmntent_r, fp, mntbuf, buf, buflen);
|
|
|
|
__sanitizer_mntent *res = REAL(getmntent_r)(fp, mntbuf, buf, buflen);
|
|
|
|
if (res) write_mntent(ctx, res);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_GETMNTENT_R COMMON_INTERCEPT_FUNCTION(getmntent_r);
|
2013-10-18 17:41:43 +08:00
|
|
|
#else
|
|
|
|
#define INIT_GETMNTENT_R
|
|
|
|
#endif
|
|
|
|
|
2013-10-18 19:14:16 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STATFS
|
|
|
|
INTERCEPTOR(int, statfs, char *path, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, statfs, path, buf);
|
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-18 19:14:16 +08:00
|
|
|
int res = REAL(statfs)(path, buf);
|
|
|
|
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, fstatfs, int fd, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fstatfs, fd, buf);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-18 19:14:16 +08:00
|
|
|
int res = REAL(fstatfs)(fd, buf);
|
|
|
|
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs_sz);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_STATFS \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(statfs); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fstatfs);
|
2013-10-18 19:14:16 +08:00
|
|
|
#else
|
|
|
|
#define INIT_STATFS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_STATFS64
|
|
|
|
INTERCEPTOR(int, statfs64, char *path, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, statfs64, path, buf);
|
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-18 19:14:16 +08:00
|
|
|
int res = REAL(statfs64)(path, buf);
|
|
|
|
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, fstatfs64, int fd, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fstatfs64, fd, buf);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-18 19:14:16 +08:00
|
|
|
int res = REAL(fstatfs64)(fd, buf);
|
|
|
|
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statfs64_sz);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_STATFS64 \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(statfs64); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fstatfs64);
|
2013-10-18 19:14:16 +08:00
|
|
|
#else
|
|
|
|
#define INIT_STATFS64
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_STATVFS
|
|
|
|
INTERCEPTOR(int, statvfs, char *path, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, statvfs, path, buf);
|
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-18 19:14:16 +08:00
|
|
|
int res = REAL(statvfs)(path, buf);
|
|
|
|
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, fstatvfs, int fd, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs, fd, buf);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-18 19:14:16 +08:00
|
|
|
int res = REAL(fstatvfs)(fd, buf);
|
|
|
|
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs_sz);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_STATVFS \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(statvfs); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fstatvfs);
|
2013-10-18 19:14:16 +08:00
|
|
|
#else
|
|
|
|
#define INIT_STATVFS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_STATVFS64
|
|
|
|
INTERCEPTOR(int, statvfs64, char *path, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, statvfs64, path, buf);
|
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-18 19:14:16 +08:00
|
|
|
int res = REAL(statvfs64)(path, buf);
|
|
|
|
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, fstatvfs64, int fd, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fstatvfs64, fd, buf);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-18 19:14:16 +08:00
|
|
|
int res = REAL(fstatvfs64)(fd, buf);
|
|
|
|
if (!res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, struct_statvfs64_sz);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_STATVFS64 \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(statvfs64); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fstatvfs64);
|
2013-10-18 19:14:16 +08:00
|
|
|
#else
|
|
|
|
#define INIT_STATVFS64
|
|
|
|
#endif
|
2013-10-18 17:41:43 +08:00
|
|
|
|
2013-10-22 20:24:48 +08:00
|
|
|
#if SANITIZER_INTERCEPT_INITGROUPS
|
|
|
|
INTERCEPTOR(int, initgroups, char *user, u32 group) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, initgroups, user, group);
|
|
|
|
if (user) COMMON_INTERCEPTOR_READ_RANGE(ctx, user, REAL(strlen)(user) + 1);
|
|
|
|
int res = REAL(initgroups)(user, group);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_INITGROUPS COMMON_INTERCEPT_FUNCTION(initgroups);
|
2013-10-22 20:24:48 +08:00
|
|
|
#else
|
|
|
|
#define INIT_INITGROUPS
|
|
|
|
#endif
|
|
|
|
|
2014-07-03 22:20:56 +08:00
|
|
|
#if SANITIZER_INTERCEPT_ETHER_NTOA_ATON
|
2013-10-23 21:57:47 +08:00
|
|
|
INTERCEPTOR(char *, ether_ntoa, __sanitizer_ether_addr *addr) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa, addr);
|
|
|
|
if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
|
|
|
|
char *res = REAL(ether_ntoa)(addr);
|
2014-03-06 21:26:09 +08:00
|
|
|
if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
|
2013-10-23 21:57:47 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(__sanitizer_ether_addr *, ether_aton, char *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ether_aton, buf);
|
|
|
|
if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
|
|
|
|
__sanitizer_ether_addr *res = REAL(ether_aton)(buf);
|
2014-03-06 21:26:09 +08:00
|
|
|
if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, sizeof(*res));
|
2013-10-23 21:57:47 +08:00
|
|
|
return res;
|
|
|
|
}
|
2014-07-03 22:20:56 +08:00
|
|
|
#define INIT_ETHER_NTOA_ATON \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(ether_ntoa); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(ether_aton);
|
|
|
|
#else
|
|
|
|
#define INIT_ETHER_NTOA_ATON
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_ETHER_HOST
|
2013-10-23 21:57:47 +08:00
|
|
|
INTERCEPTOR(int, ether_ntohost, char *hostname, __sanitizer_ether_addr *addr) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ether_ntohost, hostname, addr);
|
|
|
|
if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-23 21:57:47 +08:00
|
|
|
int res = REAL(ether_ntohost)(hostname, addr);
|
|
|
|
if (!res && hostname)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, ether_hostton, char *hostname, __sanitizer_ether_addr *addr) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ether_hostton, hostname, addr);
|
|
|
|
if (hostname)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-23 21:57:47 +08:00
|
|
|
int res = REAL(ether_hostton)(hostname, addr);
|
|
|
|
if (!res && addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, ether_line, char *line, __sanitizer_ether_addr *addr,
|
|
|
|
char *hostname) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ether_line, line, addr, hostname);
|
|
|
|
if (line) COMMON_INTERCEPTOR_READ_RANGE(ctx, line, REAL(strlen)(line) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-23 21:57:47 +08:00
|
|
|
int res = REAL(ether_line)(line, addr, hostname);
|
|
|
|
if (!res) {
|
|
|
|
if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
|
|
|
|
if (hostname)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, hostname, REAL(strlen)(hostname) + 1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2014-07-03 22:20:56 +08:00
|
|
|
#define INIT_ETHER_HOST \
|
2013-11-11 19:28:30 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION(ether_ntohost); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(ether_hostton); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(ether_line);
|
2013-10-23 21:57:47 +08:00
|
|
|
#else
|
2014-07-03 22:20:56 +08:00
|
|
|
#define INIT_ETHER_HOST
|
2013-10-23 21:57:47 +08:00
|
|
|
#endif
|
|
|
|
|
2013-10-23 23:21:10 +08:00
|
|
|
#if SANITIZER_INTERCEPT_ETHER_R
|
|
|
|
INTERCEPTOR(char *, ether_ntoa_r, __sanitizer_ether_addr *addr, char *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ether_ntoa_r, addr, buf);
|
|
|
|
if (addr) COMMON_INTERCEPTOR_READ_RANGE(ctx, addr, sizeof(*addr));
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-23 23:21:10 +08:00
|
|
|
char *res = REAL(ether_ntoa_r)(addr, buf);
|
|
|
|
if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, REAL(strlen)(res) + 1);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(__sanitizer_ether_addr *, ether_aton_r, char *buf,
|
|
|
|
__sanitizer_ether_addr *addr) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ether_aton_r, buf, addr);
|
|
|
|
if (buf) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, REAL(strlen)(buf) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-23 23:21:10 +08:00
|
|
|
__sanitizer_ether_addr *res = REAL(ether_aton_r)(buf, addr);
|
|
|
|
if (res) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(*res));
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_ETHER_R \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(ether_ntoa_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(ether_aton_r);
|
2013-10-23 23:21:10 +08:00
|
|
|
#else
|
|
|
|
#define INIT_ETHER_R
|
|
|
|
#endif
|
|
|
|
|
2013-10-24 22:47:34 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SHMCTL
|
|
|
|
INTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, shmctl, shmid, cmd, buf);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-24 22:47:34 +08:00
|
|
|
int res = REAL(shmctl)(shmid, cmd, buf);
|
|
|
|
if (res >= 0) {
|
|
|
|
unsigned sz = 0;
|
|
|
|
if (cmd == shmctl_ipc_stat || cmd == shmctl_shm_stat)
|
2013-10-29 10:48:49 +08:00
|
|
|
sz = sizeof(__sanitizer_shmid_ds);
|
2013-10-24 22:47:34 +08:00
|
|
|
else if (cmd == shmctl_ipc_info)
|
|
|
|
sz = struct_shminfo_sz;
|
|
|
|
else if (cmd == shmctl_shm_info)
|
|
|
|
sz = struct_shm_info_sz;
|
|
|
|
if (sz) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, sz);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SHMCTL COMMON_INTERCEPT_FUNCTION(shmctl);
|
2013-10-24 22:47:34 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SHMCTL
|
|
|
|
#endif
|
|
|
|
|
2013-10-25 16:58:13 +08:00
|
|
|
#if SANITIZER_INTERCEPT_RANDOM_R
|
|
|
|
INTERCEPTOR(int, random_r, void *buf, u32 *result) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, random_r, buf, result);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-25 16:58:13 +08:00
|
|
|
int res = REAL(random_r)(buf, result);
|
|
|
|
if (!res && result)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_RANDOM_R COMMON_INTERCEPT_FUNCTION(random_r);
|
2013-10-25 16:58:13 +08:00
|
|
|
#else
|
|
|
|
#define INIT_RANDOM_R
|
|
|
|
#endif
|
|
|
|
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the REAL() call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-06-19 18:19:57 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET || \
|
|
|
|
SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSSCHED || \
|
|
|
|
SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GET || \
|
|
|
|
SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GET || \
|
|
|
|
SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GET || \
|
|
|
|
SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GET
|
|
|
|
#define INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(fn, sz) \
|
|
|
|
INTERCEPTOR(int, fn, void *attr, void *r) { \
|
|
|
|
void *ctx; \
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fn, attr, r); \
|
|
|
|
int res = REAL(fn)(attr, r); \
|
|
|
|
if (!res && r) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, r, sz); \
|
|
|
|
return res; \
|
2013-10-25 21:01:31 +08:00
|
|
|
}
|
2014-06-19 18:19:57 +08:00
|
|
|
#define INTERCEPTOR_PTHREAD_ATTR_GET(what, sz) \
|
|
|
|
INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_attr_get##what, sz)
|
|
|
|
#define INTERCEPTOR_PTHREAD_MUTEXATTR_GET(what, sz) \
|
|
|
|
INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_mutexattr_get##what, sz)
|
|
|
|
#define INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(what, sz) \
|
|
|
|
INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_rwlockattr_get##what, sz)
|
|
|
|
#define INTERCEPTOR_PTHREAD_CONDATTR_GET(what, sz) \
|
|
|
|
INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_condattr_get##what, sz)
|
|
|
|
#define INTERCEPTOR_PTHREAD_BARRIERATTR_GET(what, sz) \
|
|
|
|
INTERCEPTOR_PTHREAD_OBJECT_ATTR_GET(pthread_barrierattr_get##what, sz)
|
2013-10-25 21:01:31 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GET
|
|
|
|
INTERCEPTOR_PTHREAD_ATTR_GET(detachstate, sizeof(int))
|
|
|
|
INTERCEPTOR_PTHREAD_ATTR_GET(guardsize, sizeof(SIZE_T))
|
|
|
|
INTERCEPTOR_PTHREAD_ATTR_GET(schedparam, struct_sched_param_sz)
|
|
|
|
INTERCEPTOR_PTHREAD_ATTR_GET(schedpolicy, sizeof(int))
|
|
|
|
INTERCEPTOR_PTHREAD_ATTR_GET(scope, sizeof(int))
|
|
|
|
INTERCEPTOR_PTHREAD_ATTR_GET(stacksize, sizeof(SIZE_T))
|
|
|
|
INTERCEPTOR(int, pthread_attr_getstack, void *attr, void **addr, SIZE_T *size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getstack, attr, addr, size);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-25 21:01:31 +08:00
|
|
|
int res = REAL(pthread_attr_getstack)(attr, addr, size);
|
|
|
|
if (!res) {
|
|
|
|
if (addr) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, addr, sizeof(*addr));
|
|
|
|
if (size) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, size, sizeof(*size));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2013-11-22 18:44:31 +08:00
|
|
|
// We may need to call the real pthread_attr_getstack from the run-time
|
|
|
|
// in sanitizer_common, but we don't want to include the interception headers
|
|
|
|
// there. So, just define this function here.
|
2014-02-05 23:06:32 +08:00
|
|
|
namespace __sanitizer {
|
2014-03-17 13:00:35 +08:00
|
|
|
extern "C" {
|
2014-02-05 23:06:32 +08:00
|
|
|
int real_pthread_attr_getstack(void *attr, void **addr, SIZE_T *size) {
|
2013-11-22 18:44:31 +08:00
|
|
|
return REAL(pthread_attr_getstack)(attr, addr, size);
|
|
|
|
}
|
2014-03-17 13:00:35 +08:00
|
|
|
} // extern "C"
|
2014-02-05 23:06:32 +08:00
|
|
|
} // namespace __sanitizer
|
2013-11-22 18:44:31 +08:00
|
|
|
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PTHREAD_ATTR_GET \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_attr_getdetachstate); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_attr_getguardsize); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedparam); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_attr_getschedpolicy); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_attr_getscope); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_attr_getstacksize); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_attr_getstack);
|
2013-10-25 21:01:31 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_ATTR_GET
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETINHERITSCHED
|
|
|
|
INTERCEPTOR_PTHREAD_ATTR_GET(inheritsched, sizeof(int))
|
|
|
|
|
|
|
|
#define INIT_PTHREAD_ATTR_GETINHERITSCHED \
|
2013-11-11 19:28:30 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_attr_getinheritsched);
|
2013-10-25 21:01:31 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_ATTR_GETINHERITSCHED
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_ATTR_GETAFFINITY_NP
|
|
|
|
INTERCEPTOR(int, pthread_attr_getaffinity_np, void *attr, SIZE_T cpusetsize,
|
|
|
|
void *cpuset) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pthread_attr_getaffinity_np, attr, cpusetsize,
|
|
|
|
cpuset);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-25 21:01:31 +08:00
|
|
|
int res = REAL(pthread_attr_getaffinity_np)(attr, cpusetsize, cpuset);
|
|
|
|
if (!res && cpusetsize && cpuset)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cpuset, cpusetsize);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_PTHREAD_ATTR_GETAFFINITY_NP \
|
2013-11-11 19:28:30 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_attr_getaffinity_np);
|
2013-10-25 21:01:31 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_ATTR_GETAFFINITY_NP
|
|
|
|
#endif
|
|
|
|
|
2014-06-19 18:19:57 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPSHARED
|
|
|
|
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(pshared, sizeof(int))
|
|
|
|
#define INIT_PTHREAD_MUTEXATTR_GETPSHARED \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getpshared);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_MUTEXATTR_GETPSHARED
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETTYPE
|
|
|
|
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(type, sizeof(int))
|
|
|
|
#define INIT_PTHREAD_MUTEXATTR_GETTYPE \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_gettype);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_MUTEXATTR_GETTYPE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPROTOCOL
|
|
|
|
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(protocol, sizeof(int))
|
|
|
|
#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprotocol);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_MUTEXATTR_GETPROTOCOL
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETPRIOCEILING
|
|
|
|
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(prioceiling, sizeof(int))
|
|
|
|
#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getprioceiling);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST
|
|
|
|
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust, sizeof(int))
|
|
|
|
#define INIT_PTHREAD_MUTEXATTR_GETROBUST \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_MUTEXATTR_GETROBUST
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_MUTEXATTR_GETROBUST_NP
|
|
|
|
INTERCEPTOR_PTHREAD_MUTEXATTR_GET(robust_np, sizeof(int))
|
|
|
|
#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_mutexattr_getrobust_np);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_MUTEXATTR_GETROBUST_NP
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETPSHARED
|
|
|
|
INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(pshared, sizeof(int))
|
|
|
|
#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getpshared);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_RWLOCKATTR_GETPSHARED
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_RWLOCKATTR_GETKIND_NP
|
|
|
|
INTERCEPTOR_PTHREAD_RWLOCKATTR_GET(kind_np, sizeof(int))
|
|
|
|
#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_rwlockattr_getkind_np);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_RWLOCKATTR_GETKIND_NP
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETPSHARED
|
|
|
|
INTERCEPTOR_PTHREAD_CONDATTR_GET(pshared, sizeof(int))
|
|
|
|
#define INIT_PTHREAD_CONDATTR_GETPSHARED \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_condattr_getpshared);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_CONDATTR_GETPSHARED
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_CONDATTR_GETCLOCK
|
|
|
|
INTERCEPTOR_PTHREAD_CONDATTR_GET(clock, sizeof(int))
|
|
|
|
#define INIT_PTHREAD_CONDATTR_GETCLOCK \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_condattr_getclock);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_CONDATTR_GETCLOCK
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_BARRIERATTR_GETPSHARED
|
|
|
|
INTERCEPTOR_PTHREAD_BARRIERATTR_GET(pshared, sizeof(int)) // !mac !android
|
|
|
|
#define INIT_PTHREAD_BARRIERATTR_GETPSHARED \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_barrierattr_getpshared);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_BARRIERATTR_GETPSHARED
|
|
|
|
#endif
|
|
|
|
|
2013-10-25 23:51:48 +08:00
|
|
|
#if SANITIZER_INTERCEPT_TMPNAM
|
|
|
|
INTERCEPTOR(char *, tmpnam, char *s) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, tmpnam, s);
|
|
|
|
char *res = REAL(tmpnam)(s);
|
|
|
|
if (res) {
|
|
|
|
if (s)
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-25 23:51:48 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
|
|
|
|
else
|
2014-03-06 21:26:09 +08:00
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
|
2013-10-25 23:51:48 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_TMPNAM COMMON_INTERCEPT_FUNCTION(tmpnam);
|
2013-10-25 23:51:48 +08:00
|
|
|
#else
|
|
|
|
#define INIT_TMPNAM
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_TMPNAM_R
|
|
|
|
INTERCEPTOR(char *, tmpnam_r, char *s) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, tmpnam_r, s);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-25 23:51:48 +08:00
|
|
|
char *res = REAL(tmpnam_r)(s);
|
|
|
|
if (res && s) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, s, REAL(strlen)(s) + 1);
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_TMPNAM_R COMMON_INTERCEPT_FUNCTION(tmpnam_r);
|
2013-10-25 23:51:48 +08:00
|
|
|
#else
|
|
|
|
#define INIT_TMPNAM_R
|
|
|
|
#endif
|
|
|
|
|
2016-09-10 07:09:34 +08:00
|
|
|
#if SANITIZER_INTERCEPT_TTYNAME_R
|
|
|
|
INTERCEPTOR(int, ttyname_r, int fd, char *name, SIZE_T namesize) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ttyname_r, fd, name, namesize);
|
|
|
|
int res = REAL(ttyname_r)(fd, name, namesize);
|
|
|
|
if (res == 0)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, REAL(strlen)(name) + 1);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_TTYNAME_R COMMON_INTERCEPT_FUNCTION(ttyname_r);
|
|
|
|
#else
|
|
|
|
#define INIT_TTYNAME_R
|
|
|
|
#endif
|
|
|
|
|
2013-10-25 23:51:48 +08:00
|
|
|
#if SANITIZER_INTERCEPT_TEMPNAM
|
|
|
|
INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, tempnam, dir, pfx);
|
|
|
|
if (dir) COMMON_INTERCEPTOR_READ_RANGE(ctx, dir, REAL(strlen)(dir) + 1);
|
|
|
|
if (pfx) COMMON_INTERCEPTOR_READ_RANGE(ctx, pfx, REAL(strlen)(pfx) + 1);
|
|
|
|
char *res = REAL(tempnam)(dir, pfx);
|
2014-03-06 21:26:09 +08:00
|
|
|
if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
|
2013-10-25 23:51:48 +08:00
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_TEMPNAM COMMON_INTERCEPT_FUNCTION(tempnam);
|
2013-10-25 23:51:48 +08:00
|
|
|
#else
|
|
|
|
#define INIT_TEMPNAM
|
|
|
|
#endif
|
|
|
|
|
2017-10-26 01:09:05 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && !SANITIZER_NETBSD
|
2013-10-29 18:30:39 +08:00
|
|
|
INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name);
|
2015-04-07 02:00:26 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
|
2013-10-29 18:30:39 +08:00
|
|
|
COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name);
|
|
|
|
return REAL(pthread_setname_np)(thread, name);
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
|
2017-10-26 01:09:05 +08:00
|
|
|
#elif SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && SANITIZER_NETBSD
|
|
|
|
INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name, void *arg) {
|
|
|
|
void *ctx;
|
|
|
|
char newname[32]; // PTHREAD_MAX_NAMELEN_NP=32
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name, arg);
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
|
|
|
|
internal_snprintf(newname, sizeof(newname), name, arg);
|
|
|
|
COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, newname);
|
|
|
|
return REAL(pthread_setname_np)(thread, name, arg);
|
|
|
|
}
|
|
|
|
#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np);
|
2013-10-29 18:30:39 +08:00
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_SETNAME_NP
|
|
|
|
#endif
|
|
|
|
|
2017-12-29 07:06:51 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_GETNAME_NP
|
|
|
|
INTERCEPTOR(int, pthread_getname_np, uptr thread, char *name, SIZE_T len) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pthread_getname_np, thread, name, len);
|
|
|
|
int res = REAL(pthread_getname_np)(thread, name, len);
|
|
|
|
if (!res)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, name, internal_strnlen(name, len) + 1);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_PTHREAD_GETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_getname_np);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_GETNAME_NP
|
|
|
|
#endif
|
|
|
|
|
2013-10-30 03:49:35 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SINCOS
|
|
|
|
INTERCEPTOR(void, sincos, double x, double *sin, double *cos) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sincos, x, sin, cos);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-30 03:49:35 +08:00
|
|
|
REAL(sincos)(x, sin, cos);
|
|
|
|
if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
|
|
|
|
if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
|
|
|
|
}
|
|
|
|
INTERCEPTOR(void, sincosf, float x, float *sin, float *cos) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sincosf, x, sin, cos);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-30 03:49:35 +08:00
|
|
|
REAL(sincosf)(x, sin, cos);
|
|
|
|
if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
|
|
|
|
if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
|
|
|
|
}
|
|
|
|
INTERCEPTOR(void, sincosl, long double x, long double *sin, long double *cos) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sincosl, x, sin, cos);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-30 03:49:35 +08:00
|
|
|
REAL(sincosl)(x, sin, cos);
|
|
|
|
if (sin) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sin, sizeof(*sin));
|
|
|
|
if (cos) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, cos, sizeof(*cos));
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_SINCOS \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(sincos); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(sincosf); \
|
2016-04-28 05:24:21 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(sincosl);
|
2013-10-30 03:49:35 +08:00
|
|
|
#else
|
|
|
|
#define INIT_SINCOS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_REMQUO
|
|
|
|
INTERCEPTOR(double, remquo, double x, double y, int *quo) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, remquo, x, y, quo);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-30 03:49:35 +08:00
|
|
|
double res = REAL(remquo)(x, y, quo);
|
|
|
|
if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(float, remquof, float x, float y, int *quo) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, remquof, x, y, quo);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-30 03:49:35 +08:00
|
|
|
float res = REAL(remquof)(x, y, quo);
|
|
|
|
if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(long double, remquol, long double x, long double y, int *quo) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, remquol, x, y, quo);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-30 03:49:35 +08:00
|
|
|
long double res = REAL(remquol)(x, y, quo);
|
|
|
|
if (quo) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, quo, sizeof(*quo));
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_REMQUO \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(remquo); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(remquof); \
|
2016-04-28 05:24:21 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(remquol);
|
2013-10-30 03:49:35 +08:00
|
|
|
#else
|
|
|
|
#define INIT_REMQUO
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_LGAMMA
|
|
|
|
extern int signgam;
|
|
|
|
INTERCEPTOR(double, lgamma, double x) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, lgamma, x);
|
|
|
|
double res = REAL(lgamma)(x);
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(float, lgammaf, float x) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, lgammaf, x);
|
|
|
|
float res = REAL(lgammaf)(x);
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(long double, lgammal, long double x) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, lgammal, x);
|
|
|
|
long double res = REAL(lgammal)(x);
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &signgam, sizeof(signgam));
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_LGAMMA \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(lgamma); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(lgammaf); \
|
2016-04-28 05:24:21 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION_LDBL(lgammal);
|
2013-10-30 03:49:35 +08:00
|
|
|
#else
|
|
|
|
#define INIT_LGAMMA
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_LGAMMA_R
|
|
|
|
INTERCEPTOR(double, lgamma_r, double x, int *signp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, lgamma_r, x, signp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-30 03:49:35 +08:00
|
|
|
double res = REAL(lgamma_r)(x, signp);
|
|
|
|
if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(float, lgammaf_r, float x, int *signp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, lgammaf_r, x, signp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-30 03:49:35 +08:00
|
|
|
float res = REAL(lgammaf_r)(x, signp);
|
|
|
|
if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
|
|
|
|
return res;
|
|
|
|
}
|
2014-07-03 22:20:56 +08:00
|
|
|
#define INIT_LGAMMA_R \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(lgamma_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(lgammaf_r);
|
|
|
|
#else
|
|
|
|
#define INIT_LGAMMA_R
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_LGAMMAL_R
|
2013-10-30 03:49:35 +08:00
|
|
|
INTERCEPTOR(long double, lgammal_r, long double x, int *signp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, lgammal_r, x, signp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-30 03:49:35 +08:00
|
|
|
long double res = REAL(lgammal_r)(x, signp);
|
|
|
|
if (signp) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, signp, sizeof(*signp));
|
|
|
|
return res;
|
|
|
|
}
|
2016-04-28 05:24:21 +08:00
|
|
|
#define INIT_LGAMMAL_R COMMON_INTERCEPT_FUNCTION_LDBL(lgammal_r);
|
2013-10-30 03:49:35 +08:00
|
|
|
#else
|
2014-07-03 22:20:56 +08:00
|
|
|
#define INIT_LGAMMAL_R
|
2013-10-30 03:49:35 +08:00
|
|
|
#endif
|
|
|
|
|
2013-10-30 06:25:27 +08:00
|
|
|
#if SANITIZER_INTERCEPT_DRAND48_R
|
|
|
|
INTERCEPTOR(int, drand48_r, void *buffer, double *result) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, drand48_r, buffer, result);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-30 06:25:27 +08:00
|
|
|
int res = REAL(drand48_r)(buffer, result);
|
|
|
|
if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, lrand48_r, void *buffer, long *result) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, lrand48_r, buffer, result);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-30 06:25:27 +08:00
|
|
|
int res = REAL(lrand48_r)(buffer, result);
|
|
|
|
if (result) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, result, sizeof(*result));
|
|
|
|
return res;
|
|
|
|
}
|
2013-11-11 19:28:30 +08:00
|
|
|
#define INIT_DRAND48_R \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(drand48_r); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(lrand48_r);
|
2013-10-30 06:25:27 +08:00
|
|
|
#else
|
|
|
|
#define INIT_DRAND48_R
|
|
|
|
#endif
|
2013-10-25 23:51:48 +08:00
|
|
|
|
2014-03-28 19:21:45 +08:00
|
|
|
#if SANITIZER_INTERCEPT_RAND_R
|
|
|
|
INTERCEPTOR(int, rand_r, unsigned *seedp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, rand_r, seedp);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, seedp, sizeof(*seedp));
|
|
|
|
return REAL(rand_r)(seedp);
|
|
|
|
}
|
|
|
|
#define INIT_RAND_R COMMON_INTERCEPT_FUNCTION(rand_r);
|
|
|
|
#else
|
|
|
|
#define INIT_RAND_R
|
|
|
|
#endif
|
|
|
|
|
2013-10-31 09:17:41 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETLINE
|
|
|
|
INTERCEPTOR(SSIZE_T, getline, char **lineptr, SIZE_T *n, void *stream) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getline, lineptr, n, stream);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-10-31 09:17:41 +08:00
|
|
|
SSIZE_T res = REAL(getline)(lineptr, n, stream);
|
|
|
|
if (res > 0) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr));
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n));
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2015-04-28 18:23:52 +08:00
|
|
|
|
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt its
|
|
|
|
// metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2015-04-28 18:23:52 +08:00
|
|
|
#define GETDELIM_INTERCEPTOR_IMPL(vname) \
|
|
|
|
{ \
|
|
|
|
void *ctx; \
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, vname, lineptr, n, delim, stream); \
|
|
|
|
SSIZE_T res = REAL(vname)(lineptr, n, delim, stream); \
|
|
|
|
if (res > 0) { \
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, lineptr, sizeof(*lineptr)); \
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, n, sizeof(*n)); \
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *lineptr, res + 1); \
|
|
|
|
} \
|
|
|
|
return res; \
|
2013-10-31 09:17:41 +08:00
|
|
|
}
|
2015-04-28 18:23:52 +08:00
|
|
|
|
|
|
|
INTERCEPTOR(SSIZE_T, __getdelim, char **lineptr, SIZE_T *n, int delim,
|
|
|
|
void *stream)
|
|
|
|
GETDELIM_INTERCEPTOR_IMPL(__getdelim)
|
|
|
|
|
|
|
|
// There's no __getdelim() on FreeBSD so we supply the getdelim() interceptor
|
|
|
|
// with its own body.
|
2014-06-18 21:35:13 +08:00
|
|
|
INTERCEPTOR(SSIZE_T, getdelim, char **lineptr, SIZE_T *n, int delim,
|
2015-04-28 18:23:52 +08:00
|
|
|
void *stream)
|
|
|
|
GETDELIM_INTERCEPTOR_IMPL(getdelim)
|
|
|
|
|
2014-06-18 21:35:13 +08:00
|
|
|
#define INIT_GETLINE \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getline); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__getdelim); \
|
2013-11-11 19:28:30 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION(getdelim);
|
2013-10-31 09:17:41 +08:00
|
|
|
#else
|
|
|
|
#define INIT_GETLINE
|
|
|
|
#endif
|
|
|
|
|
2013-11-28 22:14:48 +08:00
|
|
|
#if SANITIZER_INTERCEPT_ICONV
|
|
|
|
INTERCEPTOR(SIZE_T, iconv, void *cd, char **inbuf, SIZE_T *inbytesleft,
|
|
|
|
char **outbuf, SIZE_T *outbytesleft) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, iconv, cd, inbuf, inbytesleft, outbuf,
|
|
|
|
outbytesleft);
|
|
|
|
if (inbytesleft)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, inbytesleft, sizeof(*inbytesleft));
|
|
|
|
if (inbuf && inbytesleft)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, *inbuf, *inbytesleft);
|
|
|
|
if (outbytesleft)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, outbytesleft, sizeof(*outbytesleft));
|
2015-09-30 02:23:36 +08:00
|
|
|
void *outbuf_orig = outbuf ? *outbuf : nullptr;
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-11-28 22:14:48 +08:00
|
|
|
SIZE_T res = REAL(iconv)(cd, inbuf, inbytesleft, outbuf, outbytesleft);
|
2017-04-12 08:12:34 +08:00
|
|
|
if (outbuf && *outbuf > outbuf_orig) {
|
2013-11-28 22:14:48 +08:00
|
|
|
SIZE_T sz = (char *)*outbuf - (char *)outbuf_orig;
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, outbuf_orig, sz);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_ICONV COMMON_INTERCEPT_FUNCTION(iconv);
|
|
|
|
#else
|
|
|
|
#define INIT_ICONV
|
|
|
|
#endif
|
|
|
|
|
2013-11-28 22:41:22 +08:00
|
|
|
#if SANITIZER_INTERCEPT_TIMES
|
|
|
|
INTERCEPTOR(__sanitizer_clock_t, times, void *tms) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, times, tms);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2013-11-28 22:41:22 +08:00
|
|
|
__sanitizer_clock_t res = REAL(times)(tms);
|
|
|
|
if (res != (__sanitizer_clock_t)-1 && tms)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tms, struct_tms_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_TIMES COMMON_INTERCEPT_FUNCTION(times);
|
2014-01-29 18:26:38 +08:00
|
|
|
#else
|
|
|
|
#define INIT_TIMES
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_TLS_GET_ADDR
|
2016-06-18 04:24:35 +08:00
|
|
|
#if !SANITIZER_S390
|
2014-01-29 18:26:38 +08:00
|
|
|
#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr)
|
2014-12-19 02:39:55 +08:00
|
|
|
// If you see any crashes around this functions, there are 2 known issues with
|
|
|
|
// it: 1. __tls_get_addr can be called with mis-aligned stack due to:
|
|
|
|
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58066
|
|
|
|
// 2. It can be called recursively if sanitizer code uses __tls_get_addr
|
|
|
|
// to access thread local variables (it should not happen normally,
|
|
|
|
// because sanitizers use initial-exec tls model).
|
2014-01-29 17:29:16 +08:00
|
|
|
INTERCEPTOR(void *, __tls_get_addr, void *arg) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr, arg);
|
|
|
|
void *res = REAL(__tls_get_addr)(arg);
|
2015-05-16 08:34:15 +08:00
|
|
|
uptr tls_begin, tls_end;
|
|
|
|
COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
|
|
|
|
DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, tls_begin, tls_end);
|
2014-06-25 19:30:35 +08:00
|
|
|
if (dtv) {
|
|
|
|
// New DTLS block has been allocated.
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
|
|
|
|
}
|
2014-01-29 17:29:16 +08:00
|
|
|
return res;
|
|
|
|
}
|
2016-06-21 15:09:36 +08:00
|
|
|
#if SANITIZER_PPC
|
|
|
|
// On PowerPC, we also need to intercept __tls_get_addr_opt, which has
|
|
|
|
// mostly the same semantics as __tls_get_addr, but its presence enables
|
|
|
|
// some optimizations in linker (which are safe to ignore here).
|
|
|
|
extern "C" __attribute__((alias("__interceptor___tls_get_addr"),
|
|
|
|
visibility("default")))
|
|
|
|
void *__tls_get_addr_opt(void *arg);
|
|
|
|
#endif
|
2016-06-18 04:24:35 +08:00
|
|
|
#else // SANITIZER_S390
|
|
|
|
// On s390, we have to intercept two functions here:
|
|
|
|
// - __tls_get_addr_internal, which is a glibc-internal function that is like
|
|
|
|
// the usual __tls_get_addr, but returns a TP-relative offset instead of
|
|
|
|
// a proper pointer. It is used by dlsym for TLS symbols.
|
|
|
|
// - __tls_get_offset, which is like the above, but also takes a GOT-relative
|
|
|
|
// descriptor offset as an argument instead of a pointer. GOT address
|
|
|
|
// is passed in r12, so it's necessary to write it in assembly. This is
|
|
|
|
// the function used by the compiler.
|
2017-02-11 06:11:07 +08:00
|
|
|
extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
|
|
|
|
#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset)
|
|
|
|
DEFINE_REAL(uptr, __tls_get_offset, void *arg)
|
|
|
|
extern "C" uptr __tls_get_offset(void *arg);
|
|
|
|
extern "C" uptr __interceptor___tls_get_offset(void *arg);
|
2016-06-18 04:24:35 +08:00
|
|
|
INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg);
|
2017-02-11 06:11:07 +08:00
|
|
|
uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset));
|
2016-06-18 04:24:35 +08:00
|
|
|
uptr tp = reinterpret_cast<uptr>(__builtin_thread_pointer());
|
|
|
|
void *ptr = reinterpret_cast<void *>(res + tp);
|
|
|
|
uptr tls_begin, tls_end;
|
|
|
|
COMMON_INTERCEPTOR_GET_TLS_RANGE(&tls_begin, &tls_end);
|
|
|
|
DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, ptr, tls_begin, tls_end);
|
|
|
|
if (dtv) {
|
|
|
|
// New DTLS block has been allocated.
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE((void *)dtv->beg, dtv->size);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2017-02-11 06:11:07 +08:00
|
|
|
// We need a hidden symbol aliasing the above, so that we can jump
|
2016-06-18 04:24:35 +08:00
|
|
|
// directly to it from the assembly below.
|
|
|
|
extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"),
|
2017-02-11 06:11:07 +08:00
|
|
|
visibility("hidden")))
|
|
|
|
uptr __tls_get_addr_hidden(void *arg);
|
2016-06-18 04:24:35 +08:00
|
|
|
// Now carefully intercept __tls_get_offset.
|
|
|
|
asm(
|
|
|
|
".text\n"
|
|
|
|
// The __intercept_ version has to exist, so that gen_dynamic_list.py
|
|
|
|
// exports our symbol.
|
2017-02-11 06:11:07 +08:00
|
|
|
".weak __tls_get_offset\n"
|
|
|
|
".type __tls_get_offset, @function\n"
|
|
|
|
"__tls_get_offset:\n"
|
2016-06-18 04:24:35 +08:00
|
|
|
".global __interceptor___tls_get_offset\n"
|
2017-02-11 06:11:07 +08:00
|
|
|
".type __interceptor___tls_get_offset, @function\n"
|
2016-06-18 04:24:35 +08:00
|
|
|
"__interceptor___tls_get_offset:\n"
|
|
|
|
#ifdef __s390x__
|
|
|
|
"la %r2, 0(%r2,%r12)\n"
|
2017-02-11 06:11:07 +08:00
|
|
|
"jg __tls_get_addr_hidden\n"
|
2016-06-18 04:24:35 +08:00
|
|
|
#else
|
|
|
|
"basr %r3,0\n"
|
|
|
|
"0: la %r2,0(%r2,%r12)\n"
|
|
|
|
"l %r4,1f-0b(%r3)\n"
|
|
|
|
"b 0(%r4,%r3)\n"
|
2017-02-11 06:11:07 +08:00
|
|
|
"1: .long __tls_get_addr_hidden - 0b\n"
|
2016-06-18 04:24:35 +08:00
|
|
|
#endif
|
2017-02-11 06:11:07 +08:00
|
|
|
".size __interceptor___tls_get_offset, .-__interceptor___tls_get_offset\n"
|
|
|
|
// Assembly wrapper to call REAL(__tls_get_offset)(arg)
|
|
|
|
".type __tls_get_offset_wrapper, @function\n"
|
|
|
|
"__tls_get_offset_wrapper:\n"
|
|
|
|
#ifdef __s390x__
|
|
|
|
"sgr %r2,%r12\n"
|
|
|
|
#else
|
|
|
|
"sr %r2,%r12\n"
|
|
|
|
#endif
|
|
|
|
"br %r3\n"
|
|
|
|
".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n"
|
2016-06-18 04:24:35 +08:00
|
|
|
);
|
|
|
|
#endif // SANITIZER_S390
|
2013-11-28 22:41:22 +08:00
|
|
|
#else
|
2014-01-29 17:29:16 +08:00
|
|
|
#define INIT_TLS_GET_ADDR
|
|
|
|
#endif
|
|
|
|
|
2014-01-30 20:21:12 +08:00
|
|
|
#if SANITIZER_INTERCEPT_LISTXATTR
|
|
|
|
INTERCEPTOR(SSIZE_T, listxattr, const char *path, char *list, SIZE_T size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, listxattr, path, list, size);
|
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-01-30 20:21:12 +08:00
|
|
|
SSIZE_T res = REAL(listxattr)(path, list, size);
|
|
|
|
// Here and below, size == 0 is a special case where nothing is written to the
|
|
|
|
// buffer, and res contains the desired buffer size.
|
|
|
|
if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(SSIZE_T, llistxattr, const char *path, char *list, SIZE_T size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, llistxattr, path, list, size);
|
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-01-30 20:21:12 +08:00
|
|
|
SSIZE_T res = REAL(llistxattr)(path, list, size);
|
|
|
|
if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(SSIZE_T, flistxattr, int fd, char *list, SIZE_T size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, flistxattr, fd, list, size);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-01-30 20:21:12 +08:00
|
|
|
SSIZE_T res = REAL(flistxattr)(fd, list, size);
|
|
|
|
if (size && res > 0 && list) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, list, res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_LISTXATTR \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(listxattr); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(llistxattr); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(flistxattr);
|
|
|
|
#else
|
|
|
|
#define INIT_LISTXATTR
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_GETXATTR
|
|
|
|
INTERCEPTOR(SSIZE_T, getxattr, const char *path, const char *name, char *value,
|
|
|
|
SIZE_T size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getxattr, path, name, value, size);
|
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
|
|
|
if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-01-30 20:21:12 +08:00
|
|
|
SSIZE_T res = REAL(getxattr)(path, name, value, size);
|
|
|
|
if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(SSIZE_T, lgetxattr, const char *path, const char *name, char *value,
|
|
|
|
SIZE_T size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, lgetxattr, path, name, value, size);
|
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
|
|
|
if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-01-30 20:21:12 +08:00
|
|
|
SSIZE_T res = REAL(lgetxattr)(path, name, value, size);
|
|
|
|
if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(SSIZE_T, fgetxattr, int fd, const char *name, char *value,
|
|
|
|
SIZE_T size) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fgetxattr, fd, name, value, size);
|
|
|
|
if (name) COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-01-30 20:21:12 +08:00
|
|
|
SSIZE_T res = REAL(fgetxattr)(fd, name, value, size);
|
|
|
|
if (size && res > 0 && value) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_GETXATTR \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getxattr); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(lgetxattr); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fgetxattr);
|
|
|
|
#else
|
|
|
|
#define INIT_GETXATTR
|
|
|
|
#endif
|
|
|
|
|
2014-02-06 23:12:56 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETRESID
|
|
|
|
INTERCEPTOR(int, getresuid, void *ruid, void *euid, void *suid) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getresuid, ruid, euid, suid);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-02-06 23:12:56 +08:00
|
|
|
int res = REAL(getresuid)(ruid, euid, suid);
|
|
|
|
if (res >= 0) {
|
|
|
|
if (ruid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ruid, uid_t_sz);
|
|
|
|
if (euid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, euid, uid_t_sz);
|
|
|
|
if (suid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, suid, uid_t_sz);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, getresgid, void *rgid, void *egid, void *sgid) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getresgid, rgid, egid, sgid);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-02-06 23:12:56 +08:00
|
|
|
int res = REAL(getresgid)(rgid, egid, sgid);
|
|
|
|
if (res >= 0) {
|
|
|
|
if (rgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, rgid, gid_t_sz);
|
|
|
|
if (egid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, egid, gid_t_sz);
|
|
|
|
if (sgid) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sgid, gid_t_sz);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_GETRESID \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getresuid); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getresgid);
|
|
|
|
#else
|
|
|
|
#define INIT_GETRESID
|
|
|
|
#endif
|
2014-01-30 20:21:12 +08:00
|
|
|
|
2014-02-07 01:42:36 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETIFADDRS
|
|
|
|
// As long as getifaddrs()/freeifaddrs() use calloc()/free(), we don't need to
|
|
|
|
// intercept freeifaddrs(). If that ceases to be the case, we might need to
|
|
|
|
// intercept it to poison the memory again.
|
2014-02-07 02:48:23 +08:00
|
|
|
INTERCEPTOR(int, getifaddrs, __sanitizer_ifaddrs **ifap) {
|
2014-02-07 01:42:36 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getifaddrs, ifap);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-02-07 01:42:36 +08:00
|
|
|
int res = REAL(getifaddrs)(ifap);
|
|
|
|
if (res == 0 && ifap) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifap, sizeof(void *));
|
2014-02-07 02:48:23 +08:00
|
|
|
__sanitizer_ifaddrs *p = *ifap;
|
2014-02-07 01:42:36 +08:00
|
|
|
while (p) {
|
2014-02-07 02:48:23 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_ifaddrs));
|
|
|
|
if (p->ifa_name)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_name,
|
|
|
|
REAL(strlen)(p->ifa_name) + 1);
|
|
|
|
if (p->ifa_addr)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_addr, struct_sockaddr_sz);
|
|
|
|
if (p->ifa_netmask)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_netmask, struct_sockaddr_sz);
|
2014-02-07 03:36:10 +08:00
|
|
|
// On Linux this is a union, but the other member also points to a
|
|
|
|
// struct sockaddr, so the following is sufficient.
|
|
|
|
if (p->ifa_dstaddr)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ifa_dstaddr, struct_sockaddr_sz);
|
2014-02-07 02:48:23 +08:00
|
|
|
// FIXME(smatveev): Unpoison p->ifa_data as well.
|
|
|
|
p = p->ifa_next;
|
2014-02-07 01:42:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_GETIFADDRS \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getifaddrs);
|
|
|
|
#else
|
|
|
|
#define INIT_GETIFADDRS
|
|
|
|
#endif
|
|
|
|
|
2014-02-07 04:39:33 +08:00
|
|
|
#if SANITIZER_INTERCEPT_IF_INDEXTONAME
|
|
|
|
INTERCEPTOR(char *, if_indextoname, unsigned int ifindex, char* ifname) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, if_indextoname, ifindex, ifname);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-02-07 04:39:33 +08:00
|
|
|
char *res = REAL(if_indextoname)(ifindex, ifname);
|
|
|
|
if (res && ifname)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(unsigned int, if_nametoindex, const char* ifname) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, if_nametoindex, ifname);
|
|
|
|
if (ifname)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, ifname, REAL(strlen)(ifname) + 1);
|
|
|
|
return REAL(if_nametoindex)(ifname);
|
|
|
|
}
|
|
|
|
#define INIT_IF_INDEXTONAME \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(if_indextoname); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(if_nametoindex);
|
|
|
|
#else
|
|
|
|
#define INIT_IF_INDEXTONAME
|
|
|
|
#endif
|
|
|
|
|
2014-02-13 03:29:49 +08:00
|
|
|
#if SANITIZER_INTERCEPT_CAPGET
|
|
|
|
INTERCEPTOR(int, capget, void *hdrp, void *datap) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, capget, hdrp, datap);
|
|
|
|
if (hdrp)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-02-13 03:29:49 +08:00
|
|
|
int res = REAL(capget)(hdrp, datap);
|
|
|
|
if (res == 0 && datap)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, datap, __user_cap_data_struct_sz);
|
|
|
|
// We can also return -1 and write to hdrp->version if the version passed in
|
|
|
|
// hdrp->version is unsupported. But that's not a trivial condition to check,
|
|
|
|
// and anyway COMMON_INTERCEPTOR_READ_RANGE protects us to some extent.
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, capset, void *hdrp, const void *datap) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, capset, hdrp, datap);
|
|
|
|
if (hdrp)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, hdrp, __user_cap_header_struct_sz);
|
|
|
|
if (datap)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, datap, __user_cap_data_struct_sz);
|
|
|
|
return REAL(capset)(hdrp, datap);
|
|
|
|
}
|
|
|
|
#define INIT_CAPGET \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(capget); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(capset);
|
|
|
|
#else
|
|
|
|
#define INIT_CAPGET
|
|
|
|
#endif
|
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
#if SANITIZER_INTERCEPT_AEABI_MEM
|
|
|
|
INTERCEPTOR(void *, __aeabi_memmove, void *to, const void *from, uptr size) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
|
2014-03-26 20:14:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
INTERCEPTOR(void *, __aeabi_memmove4, void *to, const void *from, uptr size) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
|
2014-03-26 20:14:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
INTERCEPTOR(void *, __aeabi_memmove8, void *to, const void *from, uptr size) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size);
|
2014-03-26 20:14:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
INTERCEPTOR(void *, __aeabi_memcpy, void *to, const void *from, uptr size) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
|
2014-03-26 20:14:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
INTERCEPTOR(void *, __aeabi_memcpy4, void *to, const void *from, uptr size) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
|
2014-03-26 20:14:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
INTERCEPTOR(void *, __aeabi_memcpy8, void *to, const void *from, uptr size) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size);
|
2014-03-26 20:14:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
// Note the argument order.
|
|
|
|
INTERCEPTOR(void *, __aeabi_memset, void *block, uptr size, int c) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
|
2014-03-26 20:14:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
INTERCEPTOR(void *, __aeabi_memset4, void *block, uptr size, int c) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
|
2014-03-26 20:14:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
INTERCEPTOR(void *, __aeabi_memset8, void *block, uptr size, int c) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size);
|
2014-03-26 20:14:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
INTERCEPTOR(void *, __aeabi_memclr, void *block, uptr size) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
|
2014-03-26 20:14:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
INTERCEPTOR(void *, __aeabi_memclr4, void *block, uptr size) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
|
2014-03-26 20:14:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
INTERCEPTOR(void *, __aeabi_memclr8, void *block, uptr size) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
|
2014-03-26 20:14:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-26 20:14:34 +08:00
|
|
|
#define INIT_AEABI_MEM \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__aeabi_memmove); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__aeabi_memmove4); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__aeabi_memmove8); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy4); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__aeabi_memcpy8); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__aeabi_memset); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__aeabi_memset4); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__aeabi_memset8); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__aeabi_memclr); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__aeabi_memclr4); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__aeabi_memclr8);
|
|
|
|
#else
|
|
|
|
#define INIT_AEABI_MEM
|
|
|
|
#endif // SANITIZER_INTERCEPT_AEABI_MEM
|
|
|
|
|
2014-03-27 22:20:34 +08:00
|
|
|
#if SANITIZER_INTERCEPT___BZERO
|
|
|
|
INTERCEPTOR(void *, __bzero, void *block, uptr size) {
|
2016-12-23 06:02:26 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, 0, size);
|
2014-03-27 22:20:34 +08:00
|
|
|
}
|
2016-12-23 06:02:26 +08:00
|
|
|
|
2014-03-27 22:20:34 +08:00
|
|
|
#define INIT___BZERO COMMON_INTERCEPT_FUNCTION(__bzero);
|
|
|
|
#else
|
|
|
|
#define INIT___BZERO
|
|
|
|
#endif // SANITIZER_INTERCEPT___BZERO
|
|
|
|
|
2014-03-28 16:33:32 +08:00
|
|
|
#if SANITIZER_INTERCEPT_FTIME
|
|
|
|
INTERCEPTOR(int, ftime, __sanitizer_timeb *tp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ftime, tp);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-03-28 16:33:32 +08:00
|
|
|
int res = REAL(ftime)(tp);
|
|
|
|
if (tp)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, tp, sizeof(*tp));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_FTIME COMMON_INTERCEPT_FUNCTION(ftime);
|
|
|
|
#else
|
|
|
|
#define INIT_FTIME
|
|
|
|
#endif // SANITIZER_INTERCEPT_FTIME
|
|
|
|
|
2014-04-04 22:51:23 +08:00
|
|
|
#if SANITIZER_INTERCEPT_XDR
|
|
|
|
INTERCEPTOR(void, xdrmem_create, __sanitizer_XDR *xdrs, uptr addr,
|
|
|
|
unsigned size, int op) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, xdrmem_create, xdrs, addr, size, op);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-04-04 22:51:23 +08:00
|
|
|
REAL(xdrmem_create)(xdrs, addr, size, op);
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
|
|
|
|
if (op == __sanitizer_XDR_ENCODE) {
|
|
|
|
// It's not obvious how much data individual xdr_ routines write.
|
|
|
|
// Simply unpoison the entire target buffer in advance.
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, (void *)addr, size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(void, xdrstdio_create, __sanitizer_XDR *xdrs, void *file, int op) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, xdrstdio_create, xdrs, file, op);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-04-04 22:51:23 +08:00
|
|
|
REAL(xdrstdio_create)(xdrs, file, op);
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, xdrs, sizeof(*xdrs));
|
|
|
|
}
|
|
|
|
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-04-04 22:51:23 +08:00
|
|
|
#define XDR_INTERCEPTOR(F, T) \
|
|
|
|
INTERCEPTOR(int, F, __sanitizer_XDR *xdrs, T *p) { \
|
|
|
|
void *ctx; \
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, F, xdrs, p); \
|
|
|
|
if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) \
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p)); \
|
|
|
|
int res = REAL(F)(xdrs, p); \
|
|
|
|
if (res && p && xdrs->x_op == __sanitizer_XDR_DECODE) \
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p)); \
|
|
|
|
return res; \
|
|
|
|
}
|
|
|
|
|
|
|
|
XDR_INTERCEPTOR(xdr_short, short)
|
|
|
|
XDR_INTERCEPTOR(xdr_u_short, unsigned short)
|
|
|
|
XDR_INTERCEPTOR(xdr_int, int)
|
|
|
|
XDR_INTERCEPTOR(xdr_u_int, unsigned)
|
|
|
|
XDR_INTERCEPTOR(xdr_long, long)
|
|
|
|
XDR_INTERCEPTOR(xdr_u_long, unsigned long)
|
|
|
|
XDR_INTERCEPTOR(xdr_hyper, long long)
|
|
|
|
XDR_INTERCEPTOR(xdr_u_hyper, unsigned long long)
|
|
|
|
XDR_INTERCEPTOR(xdr_longlong_t, long long)
|
|
|
|
XDR_INTERCEPTOR(xdr_u_longlong_t, unsigned long long)
|
|
|
|
XDR_INTERCEPTOR(xdr_int8_t, u8)
|
|
|
|
XDR_INTERCEPTOR(xdr_uint8_t, u8)
|
|
|
|
XDR_INTERCEPTOR(xdr_int16_t, u16)
|
|
|
|
XDR_INTERCEPTOR(xdr_uint16_t, u16)
|
|
|
|
XDR_INTERCEPTOR(xdr_int32_t, u32)
|
|
|
|
XDR_INTERCEPTOR(xdr_uint32_t, u32)
|
|
|
|
XDR_INTERCEPTOR(xdr_int64_t, u64)
|
|
|
|
XDR_INTERCEPTOR(xdr_uint64_t, u64)
|
|
|
|
XDR_INTERCEPTOR(xdr_quad_t, long long)
|
|
|
|
XDR_INTERCEPTOR(xdr_u_quad_t, unsigned long long)
|
|
|
|
XDR_INTERCEPTOR(xdr_bool, bool)
|
|
|
|
XDR_INTERCEPTOR(xdr_enum, int)
|
|
|
|
XDR_INTERCEPTOR(xdr_char, char)
|
|
|
|
XDR_INTERCEPTOR(xdr_u_char, unsigned char)
|
|
|
|
XDR_INTERCEPTOR(xdr_float, float)
|
|
|
|
XDR_INTERCEPTOR(xdr_double, double)
|
|
|
|
|
|
|
|
// FIXME: intercept xdr_array, opaque, union, vector, reference, pointer,
|
|
|
|
// wrapstring, sizeof
|
|
|
|
|
|
|
|
INTERCEPTOR(int, xdr_bytes, __sanitizer_XDR *xdrs, char **p, unsigned *sizep,
|
|
|
|
unsigned maxsize) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, xdr_bytes, xdrs, p, sizep, maxsize);
|
|
|
|
if (p && sizep && xdrs->x_op == __sanitizer_XDR_ENCODE) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, sizep, sizeof(*sizep));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, *sizep);
|
|
|
|
}
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-04-04 22:51:23 +08:00
|
|
|
int res = REAL(xdr_bytes)(xdrs, p, sizep, maxsize);
|
|
|
|
if (p && sizep && xdrs->x_op == __sanitizer_XDR_DECODE) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizep, sizeof(*sizep));
|
|
|
|
if (res && *p && *sizep) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, *sizep);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, xdr_string, __sanitizer_XDR *xdrs, char **p,
|
|
|
|
unsigned maxsize) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, xdr_string, xdrs, p, maxsize);
|
|
|
|
if (p && xdrs->x_op == __sanitizer_XDR_ENCODE) {
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, p, sizeof(*p));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
|
|
|
|
}
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-04-04 22:51:23 +08:00
|
|
|
int res = REAL(xdr_string)(xdrs, p, maxsize);
|
|
|
|
if (p && xdrs->x_op == __sanitizer_XDR_DECODE) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(*p));
|
|
|
|
if (res && *p)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, *p, REAL(strlen)(*p) + 1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_XDR \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdrmem_create); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdrstdio_create); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_short); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_u_short); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_int); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_u_int); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_long); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_u_long); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_hyper); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_u_hyper); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_longlong_t); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_u_longlong_t); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_int8_t); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_uint8_t); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_int16_t); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_uint16_t); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_int32_t); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_uint32_t); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_int64_t); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_uint64_t); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_quad_t); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_u_quad_t); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_bool); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_enum); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_char); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_u_char); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_float); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_double); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_bytes); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(xdr_string);
|
|
|
|
#else
|
|
|
|
#define INIT_XDR
|
|
|
|
#endif // SANITIZER_INTERCEPT_XDR
|
|
|
|
|
2014-04-21 22:21:51 +08:00
|
|
|
#if SANITIZER_INTERCEPT_TSEARCH
|
|
|
|
INTERCEPTOR(void *, tsearch, void *key, void **rootp,
|
|
|
|
int (*compar)(const void *, const void *)) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, tsearch, key, rootp, compar);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-04-21 22:21:51 +08:00
|
|
|
void *res = REAL(tsearch)(key, rootp, compar);
|
|
|
|
if (res && *(void **)res == key)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, res, sizeof(void *));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_TSEARCH COMMON_INTERCEPT_FUNCTION(tsearch);
|
|
|
|
#else
|
|
|
|
#define INIT_TSEARCH
|
|
|
|
#endif
|
|
|
|
|
2014-04-25 21:26:21 +08:00
|
|
|
#if SANITIZER_INTERCEPT_LIBIO_INTERNALS || SANITIZER_INTERCEPT_FOPEN || \
|
|
|
|
SANITIZER_INTERCEPT_OPEN_MEMSTREAM
|
|
|
|
void unpoison_file(__sanitizer_FILE *fp) {
|
2014-05-13 16:36:31 +08:00
|
|
|
#if SANITIZER_HAS_STRUCT_FILE
|
2014-04-25 21:26:21 +08:00
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp, sizeof(*fp));
|
|
|
|
if (fp->_IO_read_base && fp->_IO_read_base < fp->_IO_read_end)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(fp->_IO_read_base,
|
|
|
|
fp->_IO_read_end - fp->_IO_read_base);
|
2014-05-13 16:36:31 +08:00
|
|
|
#endif // SANITIZER_HAS_STRUCT_FILE
|
2014-04-25 21:26:21 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_LIBIO_INTERNALS
|
|
|
|
// These guys are called when a .c source is built with -O2.
|
|
|
|
INTERCEPTOR(int, __uflow, __sanitizer_FILE *fp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __uflow, fp);
|
|
|
|
int res = REAL(__uflow)(fp);
|
|
|
|
unpoison_file(fp);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, __underflow, __sanitizer_FILE *fp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __underflow, fp);
|
|
|
|
int res = REAL(__underflow)(fp);
|
|
|
|
unpoison_file(fp);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, __overflow, __sanitizer_FILE *fp, int ch) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __overflow, fp, ch);
|
|
|
|
int res = REAL(__overflow)(fp, ch);
|
|
|
|
unpoison_file(fp);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, __wuflow, __sanitizer_FILE *fp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __wuflow, fp);
|
|
|
|
int res = REAL(__wuflow)(fp);
|
|
|
|
unpoison_file(fp);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, __wunderflow, __sanitizer_FILE *fp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __wunderflow, fp);
|
|
|
|
int res = REAL(__wunderflow)(fp);
|
|
|
|
unpoison_file(fp);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, __woverflow, __sanitizer_FILE *fp, int ch) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __woverflow, fp, ch);
|
|
|
|
int res = REAL(__woverflow)(fp, ch);
|
|
|
|
unpoison_file(fp);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_LIBIO_INTERNALS \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__uflow); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__underflow); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__overflow); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__wuflow); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__wunderflow); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__woverflow);
|
|
|
|
#else
|
|
|
|
#define INIT_LIBIO_INTERNALS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_FOPEN
|
|
|
|
INTERCEPTOR(__sanitizer_FILE *, fopen, const char *path, const char *mode) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fopen, path, mode);
|
2015-12-22 03:22:26 +08:00
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
2014-04-25 21:26:21 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
|
|
|
|
__sanitizer_FILE *res = REAL(fopen)(path, mode);
|
|
|
|
COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
|
|
|
|
if (res) unpoison_file(res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(__sanitizer_FILE *, fdopen, int fd, const char *mode) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fdopen, fd, mode);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
|
|
|
|
__sanitizer_FILE *res = REAL(fdopen)(fd, mode);
|
|
|
|
if (res) unpoison_file(res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(__sanitizer_FILE *, freopen, const char *path, const char *mode,
|
|
|
|
__sanitizer_FILE *fp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, freopen, path, mode, fp);
|
2015-08-31 20:41:55 +08:00
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
2014-04-25 21:26:21 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
|
|
|
|
COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
|
|
|
|
__sanitizer_FILE *res = REAL(freopen)(path, mode, fp);
|
|
|
|
COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
|
|
|
|
if (res) unpoison_file(res);
|
|
|
|
return res;
|
|
|
|
}
|
2014-05-13 20:05:38 +08:00
|
|
|
#define INIT_FOPEN \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fopen); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fdopen); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(freopen);
|
|
|
|
#else
|
|
|
|
#define INIT_FOPEN
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_FOPEN64
|
|
|
|
INTERCEPTOR(__sanitizer_FILE *, fopen64, const char *path, const char *mode) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fopen64, path, mode);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
|
|
|
|
__sanitizer_FILE *res = REAL(fopen64)(path, mode);
|
|
|
|
COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
|
|
|
|
if (res) unpoison_file(res);
|
|
|
|
return res;
|
|
|
|
}
|
2014-04-25 21:26:21 +08:00
|
|
|
INTERCEPTOR(__sanitizer_FILE *, freopen64, const char *path, const char *mode,
|
|
|
|
__sanitizer_FILE *fp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, freopen64, path, mode, fp);
|
2015-08-31 20:41:55 +08:00
|
|
|
if (path) COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
2014-04-25 21:26:21 +08:00
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, mode, REAL(strlen)(mode) + 1);
|
|
|
|
COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
|
|
|
|
__sanitizer_FILE *res = REAL(freopen64)(path, mode, fp);
|
|
|
|
COMMON_INTERCEPTOR_FILE_OPEN(ctx, res, path);
|
|
|
|
if (res) unpoison_file(res);
|
|
|
|
return res;
|
|
|
|
}
|
2014-05-13 20:05:38 +08:00
|
|
|
#define INIT_FOPEN64 \
|
2014-04-25 21:26:21 +08:00
|
|
|
COMMON_INTERCEPT_FUNCTION(fopen64); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(freopen64);
|
|
|
|
#else
|
2014-05-13 20:05:38 +08:00
|
|
|
#define INIT_FOPEN64
|
2014-04-25 21:26:21 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_OPEN_MEMSTREAM
|
|
|
|
INTERCEPTOR(__sanitizer_FILE *, open_memstream, char **ptr, SIZE_T *sizeloc) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, open_memstream, ptr, sizeloc);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-04-25 21:26:21 +08:00
|
|
|
__sanitizer_FILE *res = REAL(open_memstream)(ptr, sizeloc);
|
|
|
|
if (res) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
|
|
|
|
unpoison_file(res);
|
2014-05-13 16:36:31 +08:00
|
|
|
FileMetadata file = {ptr, sizeloc};
|
|
|
|
SetInterceptorMetadata(res, file);
|
2014-04-25 21:26:21 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(__sanitizer_FILE *, open_wmemstream, wchar_t **ptr,
|
|
|
|
SIZE_T *sizeloc) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, open_wmemstream, ptr, sizeloc);
|
|
|
|
__sanitizer_FILE *res = REAL(open_wmemstream)(ptr, sizeloc);
|
|
|
|
if (res) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, sizeof(*ptr));
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sizeloc, sizeof(*sizeloc));
|
|
|
|
unpoison_file(res);
|
2014-05-13 16:36:31 +08:00
|
|
|
FileMetadata file = {(char **)ptr, sizeloc};
|
|
|
|
SetInterceptorMetadata(res, file);
|
2014-04-25 21:26:21 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(__sanitizer_FILE *, fmemopen, void *buf, SIZE_T size,
|
|
|
|
const char *mode) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fmemopen, buf, size, mode);
|
2014-06-18 17:27:40 +08:00
|
|
|
// FIXME: under ASan the call below may write to freed memory and corrupt
|
|
|
|
// its metadata. See
|
2015-12-05 01:50:03 +08:00
|
|
|
// https://github.com/google/sanitizers/issues/321.
|
2014-04-25 21:26:21 +08:00
|
|
|
__sanitizer_FILE *res = REAL(fmemopen)(buf, size, mode);
|
|
|
|
if (res) unpoison_file(res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_OPEN_MEMSTREAM \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(open_memstream); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(open_wmemstream); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(fmemopen);
|
|
|
|
#else
|
|
|
|
#define INIT_OPEN_MEMSTREAM
|
|
|
|
#endif
|
|
|
|
|
2014-05-07 19:50:56 +08:00
|
|
|
#if SANITIZER_INTERCEPT_OBSTACK
|
|
|
|
static void initialize_obstack(__sanitizer_obstack *obstack) {
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack, sizeof(*obstack));
|
|
|
|
if (obstack->chunk)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(obstack->chunk,
|
|
|
|
sizeof(*obstack->chunk));
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, _obstack_begin_1, __sanitizer_obstack *obstack, int sz,
|
|
|
|
int align, void *(*alloc_fn)(uptr arg, uptr sz),
|
|
|
|
void (*free_fn)(uptr arg, void *p)) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin_1, obstack, sz, align, alloc_fn,
|
|
|
|
free_fn);
|
|
|
|
int res = REAL(_obstack_begin_1)(obstack, sz, align, alloc_fn, free_fn);
|
|
|
|
if (res) initialize_obstack(obstack);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, _obstack_begin, __sanitizer_obstack *obstack, int sz,
|
|
|
|
int align, void *(*alloc_fn)(uptr sz), void (*free_fn)(void *p)) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, _obstack_begin, obstack, sz, align, alloc_fn,
|
|
|
|
free_fn);
|
|
|
|
int res = REAL(_obstack_begin)(obstack, sz, align, alloc_fn, free_fn);
|
|
|
|
if (res) initialize_obstack(obstack);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(void, _obstack_newchunk, __sanitizer_obstack *obstack, int length) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, _obstack_newchunk, obstack, length);
|
|
|
|
REAL(_obstack_newchunk)(obstack, length);
|
|
|
|
if (obstack->chunk)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(
|
|
|
|
obstack->chunk, obstack->next_free - (char *)obstack->chunk);
|
|
|
|
}
|
|
|
|
#define INIT_OBSTACK \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(_obstack_begin_1); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(_obstack_begin); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(_obstack_newchunk);
|
|
|
|
#else
|
|
|
|
#define INIT_OBSTACK
|
|
|
|
#endif
|
|
|
|
|
2014-05-13 16:36:31 +08:00
|
|
|
#if SANITIZER_INTERCEPT_FFLUSH
|
|
|
|
INTERCEPTOR(int, fflush, __sanitizer_FILE *fp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fflush, fp);
|
|
|
|
int res = REAL(fflush)(fp);
|
|
|
|
// FIXME: handle fp == NULL
|
|
|
|
if (fp) {
|
|
|
|
const FileMetadata *m = GetInterceptorMetadata(fp);
|
|
|
|
if (m) COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_FFLUSH COMMON_INTERCEPT_FUNCTION(fflush);
|
|
|
|
#else
|
|
|
|
#define INIT_FFLUSH
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_FCLOSE
|
|
|
|
INTERCEPTOR(int, fclose, __sanitizer_FILE *fp) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fclose, fp);
|
2015-07-18 00:10:37 +08:00
|
|
|
COMMON_INTERCEPTOR_FILE_CLOSE(ctx, fp);
|
|
|
|
const FileMetadata *m = GetInterceptorMetadata(fp);
|
|
|
|
int res = REAL(fclose)(fp);
|
|
|
|
if (m) {
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(*m->addr, *m->size);
|
|
|
|
DeleteInterceptorMetadata(fp);
|
2014-05-13 16:36:31 +08:00
|
|
|
}
|
2015-07-18 00:10:37 +08:00
|
|
|
return res;
|
2014-05-13 16:36:31 +08:00
|
|
|
}
|
|
|
|
#define INIT_FCLOSE COMMON_INTERCEPT_FUNCTION(fclose);
|
|
|
|
#else
|
|
|
|
#define INIT_FCLOSE
|
|
|
|
#endif
|
|
|
|
|
2014-05-27 20:37:52 +08:00
|
|
|
#if SANITIZER_INTERCEPT_DLOPEN_DLCLOSE
|
|
|
|
INTERCEPTOR(void*, dlopen, const char *filename, int flag) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlopen, filename, flag);
|
2015-04-07 02:00:26 +08:00
|
|
|
if (filename) COMMON_INTERCEPTOR_READ_STRING(ctx, filename, 0);
|
2015-02-24 08:37:27 +08:00
|
|
|
COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag);
|
2014-05-27 20:37:52 +08:00
|
|
|
void *res = REAL(dlopen)(filename, flag);
|
2017-09-27 00:12:56 +08:00
|
|
|
Symbolizer::GetOrInit()->InvalidateModuleList();
|
2014-05-27 20:37:52 +08:00
|
|
|
COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, dlclose, void *handle) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER_NOIGNORE(ctx, dlclose, handle);
|
|
|
|
int res = REAL(dlclose)(handle);
|
2017-09-27 00:12:56 +08:00
|
|
|
Symbolizer::GetOrInit()->InvalidateModuleList();
|
2014-05-27 20:37:52 +08:00
|
|
|
COMMON_INTERCEPTOR_LIBRARY_UNLOADED();
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_DLOPEN_DLCLOSE \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(dlopen); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(dlclose);
|
|
|
|
#else
|
|
|
|
#define INIT_DLOPEN_DLCLOSE
|
|
|
|
#endif
|
|
|
|
|
2014-07-14 21:07:51 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETPASS
|
|
|
|
INTERCEPTOR(char *, getpass, const char *prompt) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getpass, prompt);
|
|
|
|
if (prompt)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, prompt, REAL(strlen)(prompt)+1);
|
|
|
|
char *res = REAL(getpass)(prompt);
|
|
|
|
if (res) COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res)+1);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_GETPASS COMMON_INTERCEPT_FUNCTION(getpass);
|
|
|
|
#else
|
|
|
|
#define INIT_GETPASS
|
|
|
|
#endif
|
|
|
|
|
2014-08-07 22:21:42 +08:00
|
|
|
#if SANITIZER_INTERCEPT_TIMERFD
|
|
|
|
INTERCEPTOR(int, timerfd_settime, int fd, int flags, void *new_value,
|
|
|
|
void *old_value) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, timerfd_settime, fd, flags, new_value,
|
|
|
|
old_value);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, new_value, struct_itimerspec_sz);
|
|
|
|
int res = REAL(timerfd_settime)(fd, flags, new_value, old_value);
|
|
|
|
if (res != -1 && old_value)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, old_value, struct_itimerspec_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, timerfd_gettime, int fd, void *curr_value) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, timerfd_gettime, fd, curr_value);
|
|
|
|
int res = REAL(timerfd_gettime)(fd, curr_value);
|
|
|
|
if (res != -1 && curr_value)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, curr_value, struct_itimerspec_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_TIMERFD \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(timerfd_settime); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(timerfd_gettime);
|
|
|
|
#else
|
|
|
|
#define INIT_TIMERFD
|
|
|
|
#endif
|
|
|
|
|
2014-08-26 04:57:59 +08:00
|
|
|
#if SANITIZER_INTERCEPT_MLOCKX
|
|
|
|
// Linux kernel has a bug that leads to kernel deadlock if a process
|
|
|
|
// maps TBs of memory and then calls mlock().
|
|
|
|
static void MlockIsUnsupported() {
|
|
|
|
static atomic_uint8_t printed;
|
|
|
|
if (atomic_exchange(&printed, 1, memory_order_relaxed))
|
|
|
|
return;
|
2015-07-30 08:50:40 +08:00
|
|
|
VPrintf(1, "%s ignores mlock/mlockall/munlock/munlockall\n",
|
2014-08-26 04:57:59 +08:00
|
|
|
SanitizerToolName);
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, mlock, const void *addr, uptr len) {
|
|
|
|
MlockIsUnsupported();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, munlock, const void *addr, uptr len) {
|
|
|
|
MlockIsUnsupported();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, mlockall, int flags) {
|
|
|
|
MlockIsUnsupported();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, munlockall, void) {
|
|
|
|
MlockIsUnsupported();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_MLOCKX \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(mlock); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(munlock); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(mlockall); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(munlockall);
|
|
|
|
|
|
|
|
#else
|
|
|
|
#define INIT_MLOCKX
|
|
|
|
#endif // SANITIZER_INTERCEPT_MLOCKX
|
|
|
|
|
2015-06-19 09:28:41 +08:00
|
|
|
#if SANITIZER_INTERCEPT_FOPENCOOKIE
|
|
|
|
struct WrappedCookie {
|
|
|
|
void *real_cookie;
|
|
|
|
__sanitizer_cookie_io_functions_t real_io_funcs;
|
|
|
|
};
|
|
|
|
|
|
|
|
static uptr wrapped_read(void *cookie, char *buf, uptr size) {
|
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
|
|
|
|
WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
|
2015-07-15 04:13:42 +08:00
|
|
|
__sanitizer_cookie_io_read real_read = wrapped_cookie->real_io_funcs.read;
|
|
|
|
return real_read ? real_read(wrapped_cookie->real_cookie, buf, size) : 0;
|
2015-06-19 09:28:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static uptr wrapped_write(void *cookie, const char *buf, uptr size) {
|
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
|
|
|
|
WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
|
2015-07-15 04:13:42 +08:00
|
|
|
__sanitizer_cookie_io_write real_write = wrapped_cookie->real_io_funcs.write;
|
|
|
|
return real_write ? real_write(wrapped_cookie->real_cookie, buf, size) : size;
|
2015-06-19 09:28:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int wrapped_seek(void *cookie, u64 *offset, int whence) {
|
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(3);
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(offset, sizeof(*offset));
|
|
|
|
WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
|
2015-07-15 04:13:42 +08:00
|
|
|
__sanitizer_cookie_io_seek real_seek = wrapped_cookie->real_io_funcs.seek;
|
|
|
|
return real_seek ? real_seek(wrapped_cookie->real_cookie, offset, whence)
|
|
|
|
: -1;
|
2015-06-19 09:28:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int wrapped_close(void *cookie) {
|
|
|
|
COMMON_INTERCEPTOR_UNPOISON_PARAM(1);
|
|
|
|
WrappedCookie *wrapped_cookie = (WrappedCookie *)cookie;
|
2015-07-15 04:13:42 +08:00
|
|
|
__sanitizer_cookie_io_close real_close = wrapped_cookie->real_io_funcs.close;
|
|
|
|
int res = real_close ? real_close(wrapped_cookie->real_cookie) : 0;
|
2015-06-19 09:28:41 +08:00
|
|
|
InternalFree(wrapped_cookie);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(__sanitizer_FILE *, fopencookie, void *cookie, const char *mode,
|
|
|
|
__sanitizer_cookie_io_functions_t io_funcs) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, fopencookie, cookie, mode, io_funcs);
|
|
|
|
WrappedCookie *wrapped_cookie =
|
|
|
|
(WrappedCookie *)InternalAlloc(sizeof(WrappedCookie));
|
|
|
|
wrapped_cookie->real_cookie = cookie;
|
|
|
|
wrapped_cookie->real_io_funcs = io_funcs;
|
|
|
|
__sanitizer_FILE *res =
|
|
|
|
REAL(fopencookie)(wrapped_cookie, mode, {wrapped_read, wrapped_write,
|
|
|
|
wrapped_seek, wrapped_close});
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_FOPENCOOKIE COMMON_INTERCEPT_FUNCTION(fopencookie);
|
|
|
|
#else
|
|
|
|
#define INIT_FOPENCOOKIE
|
|
|
|
#endif // SANITIZER_INTERCEPT_FOPENCOOKIE
|
|
|
|
|
2015-08-28 02:51:18 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SEM
|
2015-10-13 05:32:30 +08:00
|
|
|
INTERCEPTOR(int, sem_init, __sanitizer_sem_t *s, int pshared, unsigned value) {
|
2015-08-28 02:51:18 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sem_init, s, pshared, value);
|
2015-10-13 05:32:30 +08:00
|
|
|
// Workaround a bug in glibc's "old" semaphore implementation by
|
|
|
|
// zero-initializing the sem_t contents. This has to be done here because
|
|
|
|
// interceptors bind to the lowest symbols version by default, hitting the
|
|
|
|
// buggy code path while the non-sanitized build of the same code works fine.
|
|
|
|
REAL(memset)(s, 0, sizeof(*s));
|
2015-08-28 02:51:18 +08:00
|
|
|
int res = REAL(sem_init)(s, pshared, value);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-10-13 05:32:30 +08:00
|
|
|
INTERCEPTOR(int, sem_destroy, __sanitizer_sem_t *s) {
|
2015-08-28 02:51:18 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sem_destroy, s);
|
|
|
|
int res = REAL(sem_destroy)(s);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-10-13 05:32:30 +08:00
|
|
|
INTERCEPTOR(int, sem_wait, __sanitizer_sem_t *s) {
|
2015-08-28 02:51:18 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sem_wait, s);
|
|
|
|
int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_wait)(s);
|
|
|
|
if (res == 0) {
|
|
|
|
COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-10-13 05:32:30 +08:00
|
|
|
INTERCEPTOR(int, sem_trywait, __sanitizer_sem_t *s) {
|
2015-08-28 02:51:18 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sem_trywait, s);
|
|
|
|
int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_trywait)(s);
|
|
|
|
if (res == 0) {
|
|
|
|
COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-10-13 05:32:30 +08:00
|
|
|
INTERCEPTOR(int, sem_timedwait, __sanitizer_sem_t *s, void *abstime) {
|
2015-08-28 02:51:18 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sem_timedwait, s, abstime);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, abstime, struct_timespec_sz);
|
|
|
|
int res = COMMON_INTERCEPTOR_BLOCK_REAL(sem_timedwait)(s, abstime);
|
|
|
|
if (res == 0) {
|
|
|
|
COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-10-13 05:32:30 +08:00
|
|
|
INTERCEPTOR(int, sem_post, __sanitizer_sem_t *s) {
|
2015-08-28 02:51:18 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sem_post, s);
|
|
|
|
COMMON_INTERCEPTOR_RELEASE(ctx, (uptr)s);
|
|
|
|
int res = REAL(sem_post)(s);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2015-10-13 05:32:30 +08:00
|
|
|
INTERCEPTOR(int, sem_getvalue, __sanitizer_sem_t *s, int *sval) {
|
2015-08-28 02:51:18 +08:00
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sem_getvalue, s, sval);
|
|
|
|
int res = REAL(sem_getvalue)(s, sval);
|
|
|
|
if (res == 0) {
|
|
|
|
COMMON_INTERCEPTOR_ACQUIRE(ctx, (uptr)s);
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, sval, sizeof(*sval));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_SEM \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(sem_init); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(sem_destroy); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(sem_wait); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(sem_trywait); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(sem_timedwait); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(sem_post); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(sem_getvalue);
|
|
|
|
#else
|
|
|
|
#define INIT_SEM
|
|
|
|
#endif // SANITIZER_INTERCEPT_SEM
|
|
|
|
|
2015-10-20 07:00:13 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PTHREAD_SETCANCEL
|
|
|
|
INTERCEPTOR(int, pthread_setcancelstate, int state, int *oldstate) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcancelstate, state, oldstate);
|
|
|
|
int res = REAL(pthread_setcancelstate)(state, oldstate);
|
2017-11-07 01:43:28 +08:00
|
|
|
if (res == 0 && oldstate != nullptr)
|
2015-10-20 07:00:13 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldstate, sizeof(*oldstate));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, pthread_setcanceltype, int type, int *oldtype) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, pthread_setcanceltype, type, oldtype);
|
|
|
|
int res = REAL(pthread_setcanceltype)(type, oldtype);
|
2017-11-07 01:43:28 +08:00
|
|
|
if (res == 0 && oldtype != nullptr)
|
2015-10-20 07:00:13 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, oldtype, sizeof(*oldtype));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_PTHREAD_SETCANCEL \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_setcancelstate); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(pthread_setcanceltype);
|
|
|
|
#else
|
|
|
|
#define INIT_PTHREAD_SETCANCEL
|
|
|
|
#endif
|
|
|
|
|
2015-10-20 07:39:11 +08:00
|
|
|
#if SANITIZER_INTERCEPT_MINCORE
|
|
|
|
INTERCEPTOR(int, mincore, void *addr, uptr length, unsigned char *vec) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, mincore, addr, length, vec);
|
|
|
|
int res = REAL(mincore)(addr, length, vec);
|
|
|
|
if (res == 0) {
|
|
|
|
uptr page_size = GetPageSizeCached();
|
|
|
|
uptr vec_size = ((length + page_size - 1) & (~(page_size - 1))) / page_size;
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, vec, vec_size);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_MINCORE COMMON_INTERCEPT_FUNCTION(mincore);
|
|
|
|
#else
|
|
|
|
#define INIT_MINCORE
|
|
|
|
#endif
|
|
|
|
|
2015-10-23 04:35:42 +08:00
|
|
|
#if SANITIZER_INTERCEPT_PROCESS_VM_READV
|
|
|
|
INTERCEPTOR(SSIZE_T, process_vm_readv, int pid, __sanitizer_iovec *local_iov,
|
|
|
|
uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
|
|
|
|
uptr flags) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, process_vm_readv, pid, local_iov, liovcnt,
|
|
|
|
remote_iov, riovcnt, flags);
|
|
|
|
SSIZE_T res = REAL(process_vm_readv)(pid, local_iov, liovcnt, remote_iov,
|
|
|
|
riovcnt, flags);
|
|
|
|
if (res > 0)
|
|
|
|
write_iovec(ctx, local_iov, liovcnt, res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(SSIZE_T, process_vm_writev, int pid, __sanitizer_iovec *local_iov,
|
|
|
|
uptr liovcnt, __sanitizer_iovec *remote_iov, uptr riovcnt,
|
|
|
|
uptr flags) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, process_vm_writev, pid, local_iov, liovcnt,
|
|
|
|
remote_iov, riovcnt, flags);
|
|
|
|
SSIZE_T res = REAL(process_vm_writev)(pid, local_iov, liovcnt, remote_iov,
|
|
|
|
riovcnt, flags);
|
|
|
|
if (res > 0)
|
|
|
|
read_iovec(ctx, local_iov, liovcnt, res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_PROCESS_VM_READV \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(process_vm_readv); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(process_vm_writev);
|
|
|
|
#else
|
|
|
|
#define INIT_PROCESS_VM_READV
|
|
|
|
#endif
|
|
|
|
|
2015-12-15 06:57:49 +08:00
|
|
|
#if SANITIZER_INTERCEPT_CTERMID
|
|
|
|
INTERCEPTOR(char *, ctermid, char *s) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ctermid, s);
|
|
|
|
char *res = REAL(ctermid)(s);
|
|
|
|
if (res) {
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_CTERMID COMMON_INTERCEPT_FUNCTION(ctermid);
|
|
|
|
#else
|
|
|
|
#define INIT_CTERMID
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_CTERMID_R
|
|
|
|
INTERCEPTOR(char *, ctermid_r, char *s) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, ctermid_r, s);
|
|
|
|
char *res = REAL(ctermid_r)(s);
|
|
|
|
if (res) {
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, REAL(strlen)(res) + 1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_CTERMID_R COMMON_INTERCEPT_FUNCTION(ctermid_r);
|
|
|
|
#else
|
|
|
|
#define INIT_CTERMID_R
|
|
|
|
#endif
|
|
|
|
|
2016-02-25 16:44:25 +08:00
|
|
|
#if SANITIZER_INTERCEPT_RECV_RECVFROM
|
|
|
|
INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, recv, fd, buf, len, flags);
|
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
|
|
|
SSIZE_T res = REAL(recv)(fd, buf, len, flags);
|
|
|
|
if (res > 0) {
|
2016-05-17 15:38:27 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
|
2016-02-25 16:44:25 +08:00
|
|
|
}
|
|
|
|
if (res >= 0 && fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
|
|
|
|
void *srcaddr, int *addrlen) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, recvfrom, fd, buf, len, flags, srcaddr,
|
|
|
|
addrlen);
|
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
|
|
|
SIZE_T srcaddr_sz;
|
|
|
|
if (srcaddr) srcaddr_sz = *addrlen;
|
2016-03-01 23:36:42 +08:00
|
|
|
(void)srcaddr_sz; // prevent "set but not used" warning
|
2016-02-25 16:44:25 +08:00
|
|
|
SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen);
|
|
|
|
if (res > 0) {
|
2016-05-17 15:38:27 +08:00
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, Min((SIZE_T)res, len));
|
2016-02-25 16:44:25 +08:00
|
|
|
if (srcaddr)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr,
|
|
|
|
Min((SIZE_T)*addrlen, srcaddr_sz));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_RECV_RECVFROM \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(recv); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(recvfrom);
|
|
|
|
#else
|
|
|
|
#define INIT_RECV_RECVFROM
|
|
|
|
#endif
|
|
|
|
|
2016-06-17 08:43:11 +08:00
|
|
|
#if SANITIZER_INTERCEPT_SEND_SENDTO
|
|
|
|
INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, send, fd, buf, len, flags);
|
|
|
|
if (fd >= 0) {
|
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
|
|
|
COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
|
|
|
}
|
|
|
|
SSIZE_T res = REAL(send)(fd, buf, len, flags);
|
2016-06-21 01:57:51 +08:00
|
|
|
if (common_flags()->intercept_send && res > 0)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
|
2016-06-17 08:43:11 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
|
2016-06-21 06:05:33 +08:00
|
|
|
void *dstaddr, int addrlen) {
|
2016-06-17 08:43:11 +08:00
|
|
|
void *ctx;
|
2016-06-21 06:05:33 +08:00
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, sendto, fd, buf, len, flags, dstaddr, addrlen);
|
2016-06-17 08:43:11 +08:00
|
|
|
if (fd >= 0) {
|
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
|
|
|
COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
|
|
|
}
|
2016-06-21 06:05:33 +08:00
|
|
|
// Can't check dstaddr as it may have uninitialized padding at the end.
|
|
|
|
SSIZE_T res = REAL(sendto)(fd, buf, len, flags, dstaddr, addrlen);
|
2016-06-21 01:57:51 +08:00
|
|
|
if (common_flags()->intercept_send && res > 0)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
|
2016-06-17 08:43:11 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_SEND_SENDTO \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(send); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(sendto);
|
|
|
|
#else
|
|
|
|
#define INIT_SEND_SENDTO
|
|
|
|
#endif
|
|
|
|
|
2016-06-25 07:32:30 +08:00
|
|
|
#if SANITIZER_INTERCEPT_EVENTFD_READ_WRITE
|
|
|
|
INTERCEPTOR(int, eventfd_read, int fd, u64 *value) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, eventfd_read, fd, value);
|
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
|
|
|
int res = REAL(eventfd_read)(fd, value);
|
|
|
|
if (res == 0) {
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, value, sizeof(*value));
|
|
|
|
if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(int, eventfd_write, int fd, u64 value) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, eventfd_write, fd, value);
|
|
|
|
if (fd >= 0) {
|
|
|
|
COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
|
|
|
|
COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
|
|
|
|
}
|
|
|
|
int res = REAL(eventfd_write)(fd, value);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_EVENTFD_READ_WRITE \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(eventfd_read); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(eventfd_write)
|
|
|
|
#else
|
|
|
|
#define INIT_EVENTFD_READ_WRITE
|
|
|
|
#endif
|
|
|
|
|
2016-05-04 07:43:45 +08:00
|
|
|
#if SANITIZER_INTERCEPT_STAT
|
|
|
|
INTERCEPTOR(int, stat, const char *path, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, stat, path, buf);
|
|
|
|
if (common_flags()->intercept_stat)
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
|
|
|
|
int res = REAL(stat)(path, buf);
|
|
|
|
if (!res)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_STAT COMMON_INTERCEPT_FUNCTION(stat)
|
|
|
|
#else
|
|
|
|
#define INIT_STAT
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT___XSTAT
|
|
|
|
INTERCEPTOR(int, __xstat, int version, const char *path, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __xstat, version, path, buf);
|
|
|
|
if (common_flags()->intercept_stat)
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
|
|
|
|
int res = REAL(__xstat)(version, path, buf);
|
|
|
|
if (!res)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT___XSTAT COMMON_INTERCEPT_FUNCTION(__xstat)
|
|
|
|
#else
|
|
|
|
#define INIT___XSTAT
|
|
|
|
#endif
|
|
|
|
|
2016-05-12 04:02:15 +08:00
|
|
|
#if SANITIZER_INTERCEPT___XSTAT64
|
|
|
|
INTERCEPTOR(int, __xstat64, int version, const char *path, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __xstat64, version, path, buf);
|
|
|
|
if (common_flags()->intercept_stat)
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
|
|
|
|
int res = REAL(__xstat64)(version, path, buf);
|
|
|
|
if (!res)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT___XSTAT64 COMMON_INTERCEPT_FUNCTION(__xstat64)
|
|
|
|
#else
|
|
|
|
#define INIT___XSTAT64
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT___LXSTAT
|
|
|
|
INTERCEPTOR(int, __lxstat, int version, const char *path, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __lxstat, version, path, buf);
|
|
|
|
if (common_flags()->intercept_stat)
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
|
|
|
|
int res = REAL(__lxstat)(version, path, buf);
|
|
|
|
if (!res)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT___LXSTAT COMMON_INTERCEPT_FUNCTION(__lxstat)
|
|
|
|
#else
|
|
|
|
#define INIT___LXSTAT
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT___LXSTAT64
|
|
|
|
INTERCEPTOR(int, __lxstat64, int version, const char *path, void *buf) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, __lxstat64, version, path, buf);
|
|
|
|
if (common_flags()->intercept_stat)
|
|
|
|
COMMON_INTERCEPTOR_READ_STRING(ctx, path, 0);
|
|
|
|
int res = REAL(__lxstat64)(version, path, buf);
|
|
|
|
if (!res)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, buf, __sanitizer::struct_stat64_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT___LXSTAT64 COMMON_INTERCEPT_FUNCTION(__lxstat64)
|
|
|
|
#else
|
|
|
|
#define INIT___LXSTAT64
|
|
|
|
#endif
|
|
|
|
|
2016-05-20 00:03:10 +08:00
|
|
|
// FIXME: add other *stat interceptor
|
2016-05-04 07:43:45 +08:00
|
|
|
|
2016-12-16 06:00:14 +08:00
|
|
|
#if SANITIZER_INTERCEPT_UTMP
|
|
|
|
INTERCEPTOR(void *, getutent, int dummy) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getutent, dummy);
|
|
|
|
void *res = REAL(getutent)(dummy);
|
|
|
|
if (res)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(void *, getutid, void *ut) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getutid, ut);
|
|
|
|
void *res = REAL(getutid)(ut);
|
|
|
|
if (res)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(void *, getutline, void *ut) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getutline, ut);
|
|
|
|
void *res = REAL(getutline)(ut);
|
|
|
|
if (res)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmp_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_UTMP \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getutent); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getutid); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getutline);
|
|
|
|
#else
|
|
|
|
#define INIT_UTMP
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_UTMPX
|
|
|
|
INTERCEPTOR(void *, getutxent, int dummy) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getutxent, dummy);
|
|
|
|
void *res = REAL(getutxent)(dummy);
|
|
|
|
if (res)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(void *, getutxid, void *ut) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getutxid, ut);
|
|
|
|
void *res = REAL(getutxid)(ut);
|
|
|
|
if (res)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
INTERCEPTOR(void *, getutxline, void *ut) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getutxline, ut);
|
|
|
|
void *res = REAL(getutxline)(ut);
|
|
|
|
if (res)
|
|
|
|
COMMON_INTERCEPTOR_INITIALIZE_RANGE(res, __sanitizer::struct_utmpx_sz);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_UTMPX \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getutxent); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getutxid); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getutxline);
|
|
|
|
#else
|
|
|
|
#define INIT_UTMPX
|
|
|
|
#endif
|
|
|
|
|
2017-03-16 09:06:22 +08:00
|
|
|
#if SANITIZER_INTERCEPT_GETLOADAVG
|
|
|
|
INTERCEPTOR(int, getloadavg, double *loadavg, int nelem) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, getloadavg, loadavg, nelem);
|
|
|
|
int res = REAL(getloadavg)(loadavg, nelem);
|
|
|
|
if (res > 0)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, loadavg, res * sizeof(*loadavg));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_GETLOADAVG \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(getloadavg);
|
|
|
|
#else
|
|
|
|
#define INIT_GETLOADAVG
|
|
|
|
#endif
|
|
|
|
|
2017-05-03 15:09:10 +08:00
|
|
|
#if SANITIZER_INTERCEPT_MCHECK_MPROBE
|
|
|
|
INTERCEPTOR(int, mcheck, void (*abortfunc)(int mstatus)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, mcheck_pedantic, void (*abortfunc)(int mstatus)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, mprobe, void *ptr) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-06-28 06:52:38 +08:00
|
|
|
INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, wcslen, s);
|
|
|
|
SIZE_T res = REAL(wcslen)(s);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * (res + 1));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(SIZE_T, wcsnlen, const wchar_t *s, SIZE_T n) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, wcsnlen, s, n);
|
|
|
|
SIZE_T res = REAL(wcsnlen)(s, n);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, s, sizeof(wchar_t) * Min(res + 1, n));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
#define INIT_WCSLEN \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(wcslen); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(wcsnlen);
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_WCSCAT
|
|
|
|
INTERCEPTOR(wchar_t *, wcscat, wchar_t *dst, const wchar_t *src) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, wcscat, dst, src);
|
|
|
|
SIZE_T src_size = REAL(wcslen)(src);
|
|
|
|
SIZE_T dst_size = REAL(wcslen)(dst);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, src, (src_size + 1) * sizeof(wchar_t));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
|
|
|
|
(src_size + 1) * sizeof(wchar_t));
|
|
|
|
return REAL(wcscat)(dst, src); // NOLINT
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(wchar_t *, wcsncat, wchar_t *dst, const wchar_t *src, SIZE_T n) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, wcsncat, dst, src, n);
|
|
|
|
SIZE_T src_size = REAL(wcsnlen)(src, n);
|
|
|
|
SIZE_T dst_size = REAL(wcslen)(dst);
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, src,
|
|
|
|
Min(src_size + 1, n) * sizeof(wchar_t));
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, dst, (dst_size + 1) * sizeof(wchar_t));
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst + dst_size,
|
|
|
|
(src_size + 1) * sizeof(wchar_t));
|
|
|
|
return REAL(wcsncat)(dst, src, n); // NOLINT
|
|
|
|
}
|
|
|
|
#define INIT_WCSCAT \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(wcscat); \
|
|
|
|
COMMON_INTERCEPT_FUNCTION(wcsncat);
|
|
|
|
#else
|
|
|
|
#define INIT_WCSCAT
|
|
|
|
#endif
|
|
|
|
|
2018-01-17 21:05:14 +08:00
|
|
|
#if SANITIZER_INTERCEPT_ACCT
|
|
|
|
INTERCEPTOR(int, acct, const char *file) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, acct, file);
|
|
|
|
if (file)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, file, REAL(strlen)(file) + 1);
|
|
|
|
return REAL(acct)(file);
|
|
|
|
}
|
|
|
|
#define INIT_ACCT COMMON_INTERCEPT_FUNCTION(acct)
|
|
|
|
#else
|
|
|
|
#define INIT_ACCT
|
|
|
|
#endif
|
|
|
|
|
2018-01-18 18:53:27 +08:00
|
|
|
#if SANITIZER_INTERCEPT_USER_FROM_UID
|
|
|
|
INTERCEPTOR(const char *, user_from_uid, u32 uid, int nouser) {
|
|
|
|
void *ctx;
|
|
|
|
const char *user;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, user_from_uid, uid, nouser);
|
|
|
|
user = REAL(user_from_uid)(uid, nouser);
|
|
|
|
if (user)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, user, REAL(strlen)(user) + 1);
|
|
|
|
return user;
|
|
|
|
}
|
|
|
|
#define INIT_USER_FROM_UID COMMON_INTERCEPT_FUNCTION(user_from_uid)
|
|
|
|
#else
|
|
|
|
#define INIT_USER_FROM_UID
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_UID_FROM_USER
|
|
|
|
INTERCEPTOR(int, uid_from_user, const char *name, u32 *uid) {
|
|
|
|
void *ctx;
|
|
|
|
int res;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, uid_from_user, name, uid);
|
|
|
|
if (name)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, name, REAL(strlen)(name) + 1);
|
|
|
|
res = REAL(uid_from_user)(name, uid);
|
|
|
|
if (uid)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, uid, sizeof(*uid));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#define INIT_UID_FROM_USER COMMON_INTERCEPT_FUNCTION(uid_from_user)
|
|
|
|
#else
|
|
|
|
#define INIT_UID_FROM_USER
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_GROUP_FROM_GID
|
|
|
|
INTERCEPTOR(const char *, group_from_gid, u32 gid, int nogroup) {
|
|
|
|
void *ctx;
|
|
|
|
const char *group;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, group_from_gid, gid, nogroup);
|
|
|
|
group = REAL(group_from_gid)(gid, nogroup);
|
|
|
|
if (group)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, group, REAL(strlen)(group) + 1);
|
|
|
|
return group;
|
|
|
|
}
|
|
|
|
#define INIT_GROUP_FROM_GID COMMON_INTERCEPT_FUNCTION(group_from_gid)
|
|
|
|
#else
|
|
|
|
#define INIT_GROUP_FROM_GID
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_GID_FROM_GROUP
|
|
|
|
INTERCEPTOR(int, gid_from_group, const char *group, u32 *gid) {
|
|
|
|
void *ctx;
|
|
|
|
int res;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, gid_from_group, group, gid);
|
|
|
|
if (group)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, group, REAL(strlen)(group) + 1);
|
|
|
|
res = REAL(gid_from_group)(group, gid);
|
|
|
|
if (gid)
|
|
|
|
COMMON_INTERCEPTOR_WRITE_RANGE(ctx, gid, sizeof(*gid));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
#define INIT_GID_FROM_GROUP COMMON_INTERCEPT_FUNCTION(gid_from_group)
|
|
|
|
#else
|
|
|
|
#define INIT_GID_FROM_GROUP
|
|
|
|
#endif
|
|
|
|
|
2018-01-18 19:04:25 +08:00
|
|
|
#if SANITIZER_INTERCEPT_ACCESS
|
|
|
|
INTERCEPTOR(int, access, const char *path, int mode) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, access, path, mode);
|
|
|
|
if (path)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
|
|
|
return REAL(access)(path, mode);
|
|
|
|
}
|
|
|
|
#define INIT_ACCESS COMMON_INTERCEPT_FUNCTION(access)
|
|
|
|
#else
|
|
|
|
#define INIT_ACCESS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if SANITIZER_INTERCEPT_FACCESSAT
|
|
|
|
INTERCEPTOR(int, faccessat, int fd, const char *path, int mode, int flags) {
|
|
|
|
void *ctx;
|
|
|
|
COMMON_INTERCEPTOR_ENTER(ctx, faccessat, fd, path, mode, flags);
|
|
|
|
if (path)
|
|
|
|
COMMON_INTERCEPTOR_READ_RANGE(ctx, path, REAL(strlen)(path) + 1);
|
|
|
|
return REAL(faccessat)(fd, path, mode, flags);
|
|
|
|
}
|
|
|
|
#define INIT_FACCESSAT COMMON_INTERCEPT_FUNCTION(faccessat)
|
|
|
|
#else
|
|
|
|
#define INIT_FACCESSAT
|
|
|
|
#endif
|
|
|
|
|
2014-05-07 21:24:28 +08:00
|
|
|
static void InitializeCommonInterceptors() {
|
2014-05-13 16:36:31 +08:00
|
|
|
static u64 metadata_mem[sizeof(MetadataHashMap) / sizeof(u64) + 1];
|
|
|
|
interceptor_metadata_map = new((void *)&metadata_mem) MetadataHashMap();
|
|
|
|
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_TEXTDOMAIN;
|
2016-03-11 08:45:49 +08:00
|
|
|
INIT_STRLEN;
|
2016-03-24 05:24:28 +08:00
|
|
|
INIT_STRNLEN;
|
2017-06-01 17:37:22 +08:00
|
|
|
INIT_STRNDUP;
|
|
|
|
INIT___STRNDUP;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_STRCMP;
|
|
|
|
INIT_STRNCMP;
|
|
|
|
INIT_STRCASECMP;
|
|
|
|
INIT_STRNCASECMP;
|
2015-05-28 17:24:33 +08:00
|
|
|
INIT_STRSTR;
|
|
|
|
INIT_STRCASESTR;
|
2016-03-22 05:36:17 +08:00
|
|
|
INIT_STRCHR;
|
|
|
|
INIT_STRCHRNUL;
|
|
|
|
INIT_STRRCHR;
|
2015-05-28 17:24:33 +08:00
|
|
|
INIT_STRSPN;
|
2017-03-24 05:39:52 +08:00
|
|
|
INIT_STRTOK;
|
2015-05-28 17:24:33 +08:00
|
|
|
INIT_STRPBRK;
|
[sanitizer] Add memset, memmove, and memcpy to the common interceptors
Summary:
Currently, sanitizer_common_interceptors.inc has an implicit, undocumented
assumption that the sanitizer including it has previously declared
interceptors for memset and memmove. Since the memset, memmove, and memcpy
routines require interception by many sanitizers, we add them to the
set of common interceptions, both to address the undocumented assumption
and to speed future tool development. They are intercepted under a new
flag intercept_intrin.
The tsan interceptors are removed in favor of the new common versions. The
asan and msan interceptors for these are more complex (they incur extra
interception steps and their function bodies are exposed to the compiler)
so they opt out of the common versions and keep their own.
Reviewers: vitalybuka
Subscribers: zhaoqin, llvm-commits, kcc
Differential Revision: http://reviews.llvm.org/D18465
llvm-svn: 264451
2016-03-26 03:33:45 +08:00
|
|
|
INIT_MEMSET;
|
|
|
|
INIT_MEMMOVE;
|
|
|
|
INIT_MEMCPY;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_MEMCHR;
|
2015-07-30 07:53:08 +08:00
|
|
|
INIT_MEMCMP;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_MEMRCHR;
|
2016-07-16 05:28:58 +08:00
|
|
|
INIT_MEMMEM;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_READ;
|
2017-03-30 15:25:33 +08:00
|
|
|
INIT_FREAD;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_PREAD;
|
|
|
|
INIT_PREAD64;
|
|
|
|
INIT_READV;
|
|
|
|
INIT_PREADV;
|
|
|
|
INIT_PREADV64;
|
|
|
|
INIT_WRITE;
|
2017-03-30 15:25:33 +08:00
|
|
|
INIT_FWRITE;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_PWRITE;
|
|
|
|
INIT_PWRITE64;
|
|
|
|
INIT_WRITEV;
|
|
|
|
INIT_PWRITEV;
|
|
|
|
INIT_PWRITEV64;
|
|
|
|
INIT_PRCTL;
|
|
|
|
INIT_LOCALTIME_AND_FRIENDS;
|
|
|
|
INIT_STRPTIME;
|
|
|
|
INIT_SCANF;
|
|
|
|
INIT_ISOC99_SCANF;
|
|
|
|
INIT_PRINTF;
|
2014-12-22 20:29:40 +08:00
|
|
|
INIT_PRINTF_L;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_ISOC99_PRINTF;
|
|
|
|
INIT_FREXP;
|
|
|
|
INIT_FREXPF_FREXPL;
|
|
|
|
INIT_GETPWNAM_AND_FRIENDS;
|
|
|
|
INIT_GETPWNAM_R_AND_FRIENDS;
|
|
|
|
INIT_GETPWENT;
|
|
|
|
INIT_FGETPWENT;
|
|
|
|
INIT_GETPWENT_R;
|
|
|
|
INIT_SETPWENT;
|
|
|
|
INIT_CLOCK_GETTIME;
|
|
|
|
INIT_GETITIMER;
|
|
|
|
INIT_TIME;
|
|
|
|
INIT_GLOB;
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
INIT_GLOB64;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_WAIT;
|
|
|
|
INIT_WAIT4;
|
|
|
|
INIT_INET;
|
|
|
|
INIT_PTHREAD_GETSCHEDPARAM;
|
|
|
|
INIT_GETADDRINFO;
|
|
|
|
INIT_GETNAMEINFO;
|
|
|
|
INIT_GETSOCKNAME;
|
|
|
|
INIT_GETHOSTBYNAME;
|
[Sanitizers] Basic sanitizer Solaris support (PR 33274)
Summary:
This is the first mostly working version of the Sanitizer port to 32-bit Solaris/x86.
It is currently based on Solaris 11.4 Beta.
This part was initially developed inside libsanitizer in the GCC tree and should apply to
both. Subsequent parts will address changes to clang, the compiler-rt build system
and testsuite.
I'm not yet sure what the right patch granularity is: if it's profitable to split the patch
up, I'd like to get guidance on how to do so.
Most of the changes are probably straightforward with a few exceptions:
* The Solaris syscall interface isn't stable, undocumented and can change within an
OS release. The stable interface is the libc interface, which I'm using here, if possible
using the internal _-prefixed names.
* While the patch primarily target 32-bit x86, I've left a few sparc changes in. They
cannot currently be used with clang due to a backend limitation, but have worked
fine inside the gcc tree.
* Some functions (e.g. largefile versions of functions like open64) only exist in 32-bit
Solaris, so I've introduced a separate SANITIZER_SOLARIS32 to check for that.
The patch (with the subsequent ones to be submitted shortly) was tested
on i386-pc-solaris2.11. Only a few failures remain, some of them analyzed, some
still TBD:
AddressSanitizer-i386-sunos :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos :: TestCases/malloc-no-intercept.c
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/concurrent_overflow.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/Posix/start-deactivated.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/default_options.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/init-order-atexit.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/log-path_test.cc
AddressSanitizer-i386-sunos-dynamic :: TestCases/malloc-no-intercept.c
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/MemoryMappingLayout.DumpListOfModules
SanitizerCommon-Unit :: ./Sanitizer-i386-Test/SanitizerCommon.PthreadDestructorIterations
Maybe this is good enough the get the ball rolling.
Reviewers: kcc, alekseyshl
Reviewed By: alekseyshl
Subscribers: srhines, jyknight, kubamracek, krytarowski, fedor.sergeev, llvm-commits, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40898
llvm-svn: 320740
2017-12-15 04:14:29 +08:00
|
|
|
INIT_GETHOSTBYNAME2;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_GETHOSTBYNAME_R;
|
2014-07-03 22:20:56 +08:00
|
|
|
INIT_GETHOSTBYNAME2_R;
|
|
|
|
INIT_GETHOSTBYADDR_R;
|
|
|
|
INIT_GETHOSTENT_R;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_GETSOCKOPT;
|
|
|
|
INIT_ACCEPT;
|
|
|
|
INIT_ACCEPT4;
|
|
|
|
INIT_MODF;
|
|
|
|
INIT_RECVMSG;
|
2016-06-17 08:43:11 +08:00
|
|
|
INIT_SENDMSG;
|
2018-01-04 07:32:15 +08:00
|
|
|
INIT_RECVMMSG;
|
|
|
|
INIT_SENDMMSG;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_GETPEERNAME;
|
|
|
|
INIT_IOCTL;
|
|
|
|
INIT_INET_ATON;
|
|
|
|
INIT_SYSINFO;
|
|
|
|
INIT_READDIR;
|
|
|
|
INIT_READDIR64;
|
|
|
|
INIT_PTRACE;
|
|
|
|
INIT_SETLOCALE;
|
|
|
|
INIT_GETCWD;
|
|
|
|
INIT_GET_CURRENT_DIR_NAME;
|
|
|
|
INIT_STRTOIMAX;
|
|
|
|
INIT_MBSTOWCS;
|
|
|
|
INIT_MBSNRTOWCS;
|
|
|
|
INIT_WCSTOMBS;
|
|
|
|
INIT_WCSNRTOMBS;
|
2015-08-26 08:14:08 +08:00
|
|
|
INIT_WCRTOMB;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_TCGETATTR;
|
|
|
|
INIT_REALPATH;
|
|
|
|
INIT_CANONICALIZE_FILE_NAME;
|
|
|
|
INIT_CONFSTR;
|
|
|
|
INIT_SCHED_GETAFFINITY;
|
2015-01-22 22:03:07 +08:00
|
|
|
INIT_SCHED_GETPARAM;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_STRERROR;
|
|
|
|
INIT_STRERROR_R;
|
|
|
|
INIT_XPG_STRERROR_R;
|
|
|
|
INIT_SCANDIR;
|
|
|
|
INIT_SCANDIR64;
|
|
|
|
INIT_GETGROUPS;
|
|
|
|
INIT_POLL;
|
|
|
|
INIT_PPOLL;
|
|
|
|
INIT_WORDEXP;
|
|
|
|
INIT_SIGWAIT;
|
|
|
|
INIT_SIGWAITINFO;
|
|
|
|
INIT_SIGTIMEDWAIT;
|
|
|
|
INIT_SIGSETOPS;
|
|
|
|
INIT_SIGPENDING;
|
|
|
|
INIT_SIGPROCMASK;
|
|
|
|
INIT_BACKTRACE;
|
|
|
|
INIT__EXIT;
|
|
|
|
INIT_PTHREAD_MUTEX_LOCK;
|
|
|
|
INIT_PTHREAD_MUTEX_UNLOCK;
|
|
|
|
INIT_GETMNTENT;
|
|
|
|
INIT_GETMNTENT_R;
|
|
|
|
INIT_STATFS;
|
|
|
|
INIT_STATFS64;
|
|
|
|
INIT_STATVFS;
|
|
|
|
INIT_STATVFS64;
|
|
|
|
INIT_INITGROUPS;
|
2014-07-03 22:20:56 +08:00
|
|
|
INIT_ETHER_NTOA_ATON;
|
|
|
|
INIT_ETHER_HOST;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_ETHER_R;
|
|
|
|
INIT_SHMCTL;
|
|
|
|
INIT_RANDOM_R;
|
|
|
|
INIT_PTHREAD_ATTR_GET;
|
|
|
|
INIT_PTHREAD_ATTR_GETINHERITSCHED;
|
|
|
|
INIT_PTHREAD_ATTR_GETAFFINITY_NP;
|
2014-06-19 18:19:57 +08:00
|
|
|
INIT_PTHREAD_MUTEXATTR_GETPSHARED;
|
|
|
|
INIT_PTHREAD_MUTEXATTR_GETTYPE;
|
|
|
|
INIT_PTHREAD_MUTEXATTR_GETPROTOCOL;
|
|
|
|
INIT_PTHREAD_MUTEXATTR_GETPRIOCEILING;
|
|
|
|
INIT_PTHREAD_MUTEXATTR_GETROBUST;
|
|
|
|
INIT_PTHREAD_MUTEXATTR_GETROBUST_NP;
|
|
|
|
INIT_PTHREAD_RWLOCKATTR_GETPSHARED;
|
|
|
|
INIT_PTHREAD_RWLOCKATTR_GETKIND_NP;
|
|
|
|
INIT_PTHREAD_CONDATTR_GETPSHARED;
|
|
|
|
INIT_PTHREAD_CONDATTR_GETCLOCK;
|
|
|
|
INIT_PTHREAD_BARRIERATTR_GETPSHARED;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_TMPNAM;
|
|
|
|
INIT_TMPNAM_R;
|
2016-09-10 07:09:34 +08:00
|
|
|
INIT_TTYNAME_R;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_TEMPNAM;
|
|
|
|
INIT_PTHREAD_SETNAME_NP;
|
2017-12-29 07:06:51 +08:00
|
|
|
INIT_PTHREAD_GETNAME_NP;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_SINCOS;
|
|
|
|
INIT_REMQUO;
|
|
|
|
INIT_LGAMMA;
|
|
|
|
INIT_LGAMMA_R;
|
2014-07-03 22:20:56 +08:00
|
|
|
INIT_LGAMMAL_R;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_DRAND48_R;
|
|
|
|
INIT_RAND_R;
|
|
|
|
INIT_GETLINE;
|
|
|
|
INIT_ICONV;
|
|
|
|
INIT_TIMES;
|
|
|
|
INIT_TLS_GET_ADDR;
|
|
|
|
INIT_LISTXATTR;
|
|
|
|
INIT_GETXATTR;
|
|
|
|
INIT_GETRESID;
|
|
|
|
INIT_GETIFADDRS;
|
|
|
|
INIT_IF_INDEXTONAME;
|
|
|
|
INIT_CAPGET;
|
|
|
|
INIT_AEABI_MEM;
|
|
|
|
INIT___BZERO;
|
|
|
|
INIT_FTIME;
|
|
|
|
INIT_XDR;
|
|
|
|
INIT_TSEARCH;
|
|
|
|
INIT_LIBIO_INTERNALS;
|
|
|
|
INIT_FOPEN;
|
2014-05-13 20:05:38 +08:00
|
|
|
INIT_FOPEN64;
|
2014-05-07 21:24:28 +08:00
|
|
|
INIT_OPEN_MEMSTREAM;
|
2014-05-07 19:50:56 +08:00
|
|
|
INIT_OBSTACK;
|
2014-05-13 16:36:31 +08:00
|
|
|
INIT_FFLUSH;
|
|
|
|
INIT_FCLOSE;
|
2014-05-27 20:37:52 +08:00
|
|
|
INIT_DLOPEN_DLCLOSE;
|
2014-07-14 21:07:51 +08:00
|
|
|
INIT_GETPASS;
|
2014-08-07 22:21:42 +08:00
|
|
|
INIT_TIMERFD;
|
2014-08-26 04:57:59 +08:00
|
|
|
INIT_MLOCKX;
|
2015-06-19 09:28:41 +08:00
|
|
|
INIT_FOPENCOOKIE;
|
2015-08-28 02:51:18 +08:00
|
|
|
INIT_SEM;
|
2015-10-20 07:00:13 +08:00
|
|
|
INIT_PTHREAD_SETCANCEL;
|
2015-10-20 07:39:11 +08:00
|
|
|
INIT_MINCORE;
|
2015-10-23 04:35:42 +08:00
|
|
|
INIT_PROCESS_VM_READV;
|
2015-12-15 06:57:49 +08:00
|
|
|
INIT_CTERMID;
|
|
|
|
INIT_CTERMID_R;
|
2016-02-25 16:44:25 +08:00
|
|
|
INIT_RECV_RECVFROM;
|
2016-06-17 08:43:11 +08:00
|
|
|
INIT_SEND_SENDTO;
|
2016-05-04 07:43:45 +08:00
|
|
|
INIT_STAT;
|
2016-06-25 07:32:30 +08:00
|
|
|
INIT_EVENTFD_READ_WRITE;
|
2016-05-04 07:43:45 +08:00
|
|
|
INIT___XSTAT;
|
2016-05-12 04:02:15 +08:00
|
|
|
INIT___XSTAT64;
|
|
|
|
INIT___LXSTAT;
|
|
|
|
INIT___LXSTAT64;
|
2016-05-20 00:03:10 +08:00
|
|
|
// FIXME: add other *stat interceptors.
|
2016-12-16 06:00:14 +08:00
|
|
|
INIT_UTMP;
|
|
|
|
INIT_UTMPX;
|
2017-03-16 09:06:22 +08:00
|
|
|
INIT_GETLOADAVG;
|
2017-06-28 06:52:38 +08:00
|
|
|
INIT_WCSLEN;
|
|
|
|
INIT_WCSCAT;
|
2018-01-17 21:05:14 +08:00
|
|
|
INIT_ACCT;
|
2018-01-18 18:53:27 +08:00
|
|
|
INIT_USER_FROM_UID;
|
|
|
|
INIT_UID_FROM_USER;
|
|
|
|
INIT_GROUP_FROM_GID;
|
|
|
|
INIT_GID_FROM_GROUP;
|
2018-01-18 19:04:25 +08:00
|
|
|
INIT_ACCESS;
|
|
|
|
INIT_FACCESSAT;
|
Handle NetBSD specific indirection of libpthread functions
Summary:
Correct handling of three libpthread(3) functions on NetBSD:
- pthread_mutex_lock(3),
- pthread_mutex_unlock(3),
- pthread_setcancelstate(3).
Code out of the libpthread(3) context uses the libc symbols:
- __libc_mutex_lock,
- __libc_mutex_unlock,
- __libc_thr_setcancelstate.
The threading library (libpthread(3)) defines strong aliases:
- __strong_alias(__libc_mutex_lock,pthread_mutex_lock)
- __strong_alias(__libc_mutex_unlock,pthread_mutex_unlock)
- __strong_alias(__libc_thr_setcancelstate,pthread_setcancelstate)
This caused that these functions were invisible to sanitizers on NetBSD.
Intercept the libc-specific ones and add them as NetBSD-specific aliases
for the common pthread(3) ones.
NetBSD needs to intercept both functions, as the regularly named ones
are used internally in libpthread(3).
Sponsored by <The NetBSD Foundation>
Reviewers: joerg, dvyukov, vitalybuka
Reviewed By: dvyukov
Subscribers: llvm-commits, kubamracek, #sanitizers
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D40241
llvm-svn: 318646
2017-11-20 20:21:11 +08:00
|
|
|
|
|
|
|
#if SANITIZER_NETBSD
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__libc_mutex_lock);
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__libc_mutex_unlock);
|
|
|
|
COMMON_INTERCEPT_FUNCTION(__libc_thr_setcancelstate);
|
|
|
|
#endif
|
2017-12-18 23:31:26 +08:00
|
|
|
|
|
|
|
INIT___PRINTF_CHK;
|
2014-05-07 21:24:28 +08:00
|
|
|
}
|