2011-11-30 09:07:02 +08:00
|
|
|
//===-- asan_interceptors.h -------------------------------------*- C++ -*-===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2011-11-30 09:07:02 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file is a part of AddressSanitizer, an address sanity checker.
|
|
|
|
//
|
|
|
|
// ASan-private header for asan_interceptors.cc
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef ASAN_INTERCEPTORS_H
|
|
|
|
#define ASAN_INTERCEPTORS_H
|
|
|
|
|
|
|
|
#include "asan_internal.h"
|
2017-07-20 09:29:01 +08:00
|
|
|
#include "asan_interceptors_memintrinsics.h"
|
2014-11-18 18:33:15 +08:00
|
|
|
#include "interception/interception.h"
|
2013-12-26 23:34:31 +08:00
|
|
|
#include "sanitizer_common/sanitizer_platform_interceptors.h"
|
|
|
|
|
2017-08-02 15:59:30 +08:00
|
|
|
namespace __asan {
|
|
|
|
|
|
|
|
void InitializeAsanInterceptors();
|
|
|
|
void InitializePlatformInterceptors();
|
|
|
|
|
|
|
|
#define ENSURE_ASAN_INITED() \
|
|
|
|
do { \
|
|
|
|
CHECK(!asan_init_is_running); \
|
|
|
|
if (UNLIKELY(!asan_inited)) { \
|
|
|
|
AsanInitFromRtl(); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
} // namespace __asan
|
|
|
|
|
2018-05-18 08:43:54 +08:00
|
|
|
// There is no general interception at all on Fuchsia and RTEMS.
|
2017-08-02 15:59:30 +08:00
|
|
|
// Only the functions in asan_interceptors_memintrinsics.h are
|
|
|
|
// really defined to replace libc functions.
|
2018-05-18 08:43:54 +08:00
|
|
|
#if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
|
2017-08-02 15:59:30 +08:00
|
|
|
|
2013-12-26 23:34:31 +08:00
|
|
|
// Use macro to describe if specific function should be
|
|
|
|
// intercepted on a given platform.
|
|
|
|
#if !SANITIZER_WINDOWS
|
|
|
|
# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 1
|
|
|
|
# define ASAN_INTERCEPT__LONGJMP 1
|
|
|
|
# define ASAN_INTERCEPT_INDEX 1
|
|
|
|
# define ASAN_INTERCEPT_PTHREAD_CREATE 1
|
|
|
|
#else
|
|
|
|
# define ASAN_INTERCEPT_ATOLL_AND_STRTOLL 0
|
|
|
|
# define ASAN_INTERCEPT__LONGJMP 0
|
|
|
|
# define ASAN_INTERCEPT_INDEX 0
|
|
|
|
# define ASAN_INTERCEPT_PTHREAD_CREATE 0
|
|
|
|
#endif
|
|
|
|
|
[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_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
|
|
|
|
SANITIZER_SOLARIS
|
2013-12-26 23:34:31 +08:00
|
|
|
# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 1
|
|
|
|
#else
|
|
|
|
# define ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 0
|
|
|
|
#endif
|
|
|
|
|
[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_LINUX && !SANITIZER_ANDROID) || SANITIZER_SOLARIS
|
2013-12-26 23:34:31 +08:00
|
|
|
# define ASAN_INTERCEPT_SWAPCONTEXT 1
|
|
|
|
#else
|
|
|
|
# define ASAN_INTERCEPT_SWAPCONTEXT 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !SANITIZER_WINDOWS
|
|
|
|
# define ASAN_INTERCEPT_SIGLONGJMP 1
|
|
|
|
#else
|
|
|
|
# define ASAN_INTERCEPT_SIGLONGJMP 0
|
|
|
|
#endif
|
|
|
|
|
2017-05-04 22:03:57 +08:00
|
|
|
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
|
|
|
# define ASAN_INTERCEPT___LONGJMP_CHK 1
|
|
|
|
#else
|
|
|
|
# define ASAN_INTERCEPT___LONGJMP_CHK 0
|
|
|
|
#endif
|
|
|
|
|
2018-02-28 02:05:49 +08:00
|
|
|
#if ASAN_HAS_EXCEPTIONS && !SANITIZER_WINDOWS && !SANITIZER_SOLARIS && \
|
|
|
|
!SANITIZER_NETBSD
|
2013-12-26 23:34:31 +08:00
|
|
|
# define ASAN_INTERCEPT___CXA_THROW 1
|
[asan] Intercept std::rethrow_exception indirectly
Summary:
Fixes Bug 32434
See https://bugs.llvm.org/show_bug.cgi?id=32434
Short summary:
std::rethrow_exception does not use __cxa_throw to rethrow the exception, so if
it is called from uninstrumented code, it will leave the stack poisoned. This
can lead to false positives.
Long description:
For functions which don't return normally (e.g. via exceptions), asan needs to
unpoison the entire stack. It is not known before a call to such a function
where execution will continue, some function which don't contain cleanup code
like destructors might be skipped. After stack unwinding, execution might
continue in uninstrumented code.
If the stack has been poisoned before such a function is called, but the stack
is unwound during the unconventional return, then zombie redzones (entries) for
no longer existing stack variables can remain in the shadow memory. Normally,
this is avoided by asan generating a call to asan_handle_no_return before all
functions marked as [[noreturn]]. This asan_handle_no_return unpoisons the
entire stack. Since these [[noreturn]] functions can be called from
uninstrumented code, asan also introduces interceptor functions which call
asan_handle_no_return before running the original [[noreturn]] function;
for example, cxa_throw is intercepted.
If a [[noreturn]] function is called from uninstrumented code (so the stack is
left poisoned) and additionally, execution continues in uninstrumented code, new
stack variables might be introduced and overlap with the stack variables
which have been removed during stack unwinding. Since the redzones are not
cleared nor overwritten by uninstrumented code, they remain but now contain
invalid data.
Now, if the redzones are checked against the new stack variables, false
positive reports can occur. This can happen for example by the uninstrumented
code calling an intercepted function such as memcpy, or an instrumented
function.
Intercepting std::rethrow_exception directly is not easily possible since it
depends on the C++ standard library implementation (e.g. libcxx vs libstdc++)
and the mangled name it produces for this function. As a rather simple
workaround, we're intercepting _Unwind_RaiseException for libstdc++. For
libcxxabi, we can intercept the ABI function __cxa_rethrow_primary_exception.
Patch by Robert Schneider.
Reviewers: kcc, eugenis, alekseyshl, vitalybuka
Reviewed By: vitalybuka
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D42644
llvm-svn: 326132
2018-02-27 05:40:19 +08:00
|
|
|
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 1
|
2018-02-27 07:39:04 +08:00
|
|
|
# if defined(_GLIBCXX_SJLJ_EXCEPTIONS) || (SANITIZER_IOS && defined(__arm__))
|
[asan] Intercept std::rethrow_exception indirectly
Summary:
Fixes Bug 32434
See https://bugs.llvm.org/show_bug.cgi?id=32434
Short summary:
std::rethrow_exception does not use __cxa_throw to rethrow the exception, so if
it is called from uninstrumented code, it will leave the stack poisoned. This
can lead to false positives.
Long description:
For functions which don't return normally (e.g. via exceptions), asan needs to
unpoison the entire stack. It is not known before a call to such a function
where execution will continue, some function which don't contain cleanup code
like destructors might be skipped. After stack unwinding, execution might
continue in uninstrumented code.
If the stack has been poisoned before such a function is called, but the stack
is unwound during the unconventional return, then zombie redzones (entries) for
no longer existing stack variables can remain in the shadow memory. Normally,
this is avoided by asan generating a call to asan_handle_no_return before all
functions marked as [[noreturn]]. This asan_handle_no_return unpoisons the
entire stack. Since these [[noreturn]] functions can be called from
uninstrumented code, asan also introduces interceptor functions which call
asan_handle_no_return before running the original [[noreturn]] function;
for example, cxa_throw is intercepted.
If a [[noreturn]] function is called from uninstrumented code (so the stack is
left poisoned) and additionally, execution continues in uninstrumented code, new
stack variables might be introduced and overlap with the stack variables
which have been removed during stack unwinding. Since the redzones are not
cleared nor overwritten by uninstrumented code, they remain but now contain
invalid data.
Now, if the redzones are checked against the new stack variables, false
positive reports can occur. This can happen for example by the uninstrumented
code calling an intercepted function such as memcpy, or an instrumented
function.
Intercepting std::rethrow_exception directly is not easily possible since it
depends on the C++ standard library implementation (e.g. libcxx vs libstdc++)
and the mangled name it produces for this function. As a rather simple
workaround, we're intercepting _Unwind_RaiseException for libstdc++. For
libcxxabi, we can intercept the ABI function __cxa_rethrow_primary_exception.
Patch by Robert Schneider.
Reviewers: kcc, eugenis, alekseyshl, vitalybuka
Reviewed By: vitalybuka
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D42644
llvm-svn: 326132
2018-02-27 05:40:19 +08:00
|
|
|
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 1
|
|
|
|
# else
|
|
|
|
# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 1
|
|
|
|
# endif
|
2013-12-26 23:34:31 +08:00
|
|
|
#else
|
|
|
|
# define ASAN_INTERCEPT___CXA_THROW 0
|
[asan] Intercept std::rethrow_exception indirectly
Summary:
Fixes Bug 32434
See https://bugs.llvm.org/show_bug.cgi?id=32434
Short summary:
std::rethrow_exception does not use __cxa_throw to rethrow the exception, so if
it is called from uninstrumented code, it will leave the stack poisoned. This
can lead to false positives.
Long description:
For functions which don't return normally (e.g. via exceptions), asan needs to
unpoison the entire stack. It is not known before a call to such a function
where execution will continue, some function which don't contain cleanup code
like destructors might be skipped. After stack unwinding, execution might
continue in uninstrumented code.
If the stack has been poisoned before such a function is called, but the stack
is unwound during the unconventional return, then zombie redzones (entries) for
no longer existing stack variables can remain in the shadow memory. Normally,
this is avoided by asan generating a call to asan_handle_no_return before all
functions marked as [[noreturn]]. This asan_handle_no_return unpoisons the
entire stack. Since these [[noreturn]] functions can be called from
uninstrumented code, asan also introduces interceptor functions which call
asan_handle_no_return before running the original [[noreturn]] function;
for example, cxa_throw is intercepted.
If a [[noreturn]] function is called from uninstrumented code (so the stack is
left poisoned) and additionally, execution continues in uninstrumented code, new
stack variables might be introduced and overlap with the stack variables
which have been removed during stack unwinding. Since the redzones are not
cleared nor overwritten by uninstrumented code, they remain but now contain
invalid data.
Now, if the redzones are checked against the new stack variables, false
positive reports can occur. This can happen for example by the uninstrumented
code calling an intercepted function such as memcpy, or an instrumented
function.
Intercepting std::rethrow_exception directly is not easily possible since it
depends on the C++ standard library implementation (e.g. libcxx vs libstdc++)
and the mangled name it produces for this function. As a rather simple
workaround, we're intercepting _Unwind_RaiseException for libstdc++. For
libcxxabi, we can intercept the ABI function __cxa_rethrow_primary_exception.
Patch by Robert Schneider.
Reviewers: kcc, eugenis, alekseyshl, vitalybuka
Reviewed By: vitalybuka
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D42644
llvm-svn: 326132
2018-02-27 05:40:19 +08:00
|
|
|
# define ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 0
|
|
|
|
# define ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 0
|
|
|
|
# define ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 0
|
2013-12-26 23:34:31 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !SANITIZER_WINDOWS
|
|
|
|
# define ASAN_INTERCEPT___CXA_ATEXIT 1
|
|
|
|
#else
|
|
|
|
# define ASAN_INTERCEPT___CXA_ATEXIT 0
|
|
|
|
#endif
|
2012-02-02 18:39:40 +08:00
|
|
|
|
2016-04-21 06:45:23 +08:00
|
|
|
#if SANITIZER_LINUX && !SANITIZER_ANDROID
|
|
|
|
# define ASAN_INTERCEPT___STRDUP 1
|
|
|
|
#else
|
|
|
|
# define ASAN_INTERCEPT___STRDUP 0
|
|
|
|
#endif
|
|
|
|
|
2019-02-28 06:23:51 +08:00
|
|
|
#if SANITIZER_LINUX && (defined(__arm__) || defined(__aarch64__) || \
|
|
|
|
defined(__i386__) || defined(__x86_64__))
|
|
|
|
# define ASAN_INTERCEPT_VFORK 1
|
|
|
|
#else
|
|
|
|
# define ASAN_INTERCEPT_VFORK 0
|
|
|
|
#endif
|
|
|
|
|
2012-06-25 14:53:10 +08:00
|
|
|
DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size)
|
|
|
|
DECLARE_REAL(char*, strchr, const char *str, int c)
|
2014-08-22 00:12:46 +08:00
|
|
|
DECLARE_REAL(SIZE_T, strlen, const char *s)
|
2012-06-25 14:53:10 +08:00
|
|
|
DECLARE_REAL(char*, strncpy, char *to, const char *from, uptr size)
|
|
|
|
DECLARE_REAL(uptr, strnlen, const char *s, uptr maxlen)
|
2012-08-24 17:22:05 +08:00
|
|
|
DECLARE_REAL(char*, strstr, const char *s1, const char *s2)
|
2012-02-02 18:39:40 +08:00
|
|
|
|
2015-03-16 22:22:53 +08:00
|
|
|
#if !SANITIZER_MAC
|
2019-05-17 07:46:15 +08:00
|
|
|
#define ASAN_INTERCEPT_FUNC(name) \
|
|
|
|
do { \
|
|
|
|
if (!INTERCEPT_FUNCTION(name)) \
|
|
|
|
VReport(1, "AddressSanitizer: failed to intercept '%s'\n'", #name); \
|
2015-03-16 22:22:53 +08:00
|
|
|
} while (0)
|
2019-05-17 07:46:15 +08:00
|
|
|
#define ASAN_INTERCEPT_FUNC_VER(name, ver) \
|
|
|
|
do { \
|
|
|
|
if (!INTERCEPT_FUNCTION_VER(name, ver)) \
|
|
|
|
VReport(1, "AddressSanitizer: failed to intercept '%s@@%s'\n", #name, \
|
|
|
|
#ver); \
|
2015-09-23 05:34:44 +08:00
|
|
|
} while (0)
|
2015-03-16 22:22:53 +08:00
|
|
|
#else
|
|
|
|
// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
|
|
|
|
#define ASAN_INTERCEPT_FUNC(name)
|
|
|
|
#endif // SANITIZER_MAC
|
|
|
|
|
2017-08-02 15:59:30 +08:00
|
|
|
#endif // !SANITIZER_FUCHSIA
|
2011-11-30 09:07:02 +08:00
|
|
|
|
|
|
|
#endif // ASAN_INTERCEPTORS_H
|