2019-02-27 23:44:03 +08:00
|
|
|
//===-- hwasan_interceptors.cpp -------------------------------------------===//
|
2017-12-09 09:31:51 +08:00
|
|
|
//
|
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
|
2017-12-09 09:31:51 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file is a part of HWAddressSanitizer.
|
|
|
|
//
|
|
|
|
// Interceptors for standard library functions.
|
|
|
|
//
|
|
|
|
// FIXME: move as many interceptors as possible into
|
|
|
|
// sanitizer_common/sanitizer_common_interceptors.h
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "interception/interception.h"
|
|
|
|
#include "hwasan.h"
|
hwasan: Use system allocator to realloc and free untagged pointers in interceptor mode.
The Android dynamic loader has a non-standard feature that allows
libraries such as the hwasan runtime to interpose symbols even after
the symbol already has a value. The new value of the symbol is used to
relocate libraries loaded after the interposing library, but existing
libraries keep the old value. This behaviour is activated by the
DF_1_GLOBAL flag in DT_FLAGS_1, which is set by passing -z global to
the linker, which is what we already do to link the hwasan runtime.
What this means in practice is that if we have .so files that depend
on interceptor-mode hwasan without the main executable depending on
it, some of the libraries in the process will be using the hwasan
allocator and some will be using the system allocator, and these
allocators need to interact somehow. For example, if an instrumented
library calls a function such as strdup that allocates memory on
behalf of the caller, the instrumented library can reasonably expect
to be able to call free to deallocate the memory.
We can handle that relatively easily with hwasan by using tag 0 to
represent allocations from the system allocator. If hwasan's realloc
or free functions are passed a pointer with tag 0, the system allocator
is called.
One limitation is that this scheme doesn't work in reverse: if an
instrumented library allocates memory, it must free the memory itself
and cannot pass ownership to a system library. In a future change,
we may want to expose an API for calling the system allocator so
that instrumented libraries can safely transfer ownership of memory
to system libraries.
Differential Revision: https://reviews.llvm.org/D55986
llvm-svn: 350427
2019-01-05 03:21:51 +08:00
|
|
|
#include "hwasan_allocator.h"
|
2018-04-24 02:19:23 +08:00
|
|
|
#include "hwasan_mapping.h"
|
2017-12-09 09:31:51 +08:00
|
|
|
#include "hwasan_thread.h"
|
|
|
|
#include "hwasan_poisoning.h"
|
2018-06-08 07:33:33 +08:00
|
|
|
#include "hwasan_report.h"
|
2017-12-09 09:31:51 +08:00
|
|
|
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
|
|
|
|
#include "sanitizer_common/sanitizer_allocator.h"
|
|
|
|
#include "sanitizer_common/sanitizer_allocator_interface.h"
|
|
|
|
#include "sanitizer_common/sanitizer_allocator_internal.h"
|
|
|
|
#include "sanitizer_common/sanitizer_atomic.h"
|
|
|
|
#include "sanitizer_common/sanitizer_common.h"
|
|
|
|
#include "sanitizer_common/sanitizer_errno.h"
|
|
|
|
#include "sanitizer_common/sanitizer_stackdepot.h"
|
|
|
|
#include "sanitizer_common/sanitizer_libc.h"
|
|
|
|
#include "sanitizer_common/sanitizer_linux.h"
|
|
|
|
#include "sanitizer_common/sanitizer_tls_get_addr.h"
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
// ACHTUNG! No other system header includes in this file.
|
|
|
|
// Ideally, we should get rid of stdarg.h as well.
|
|
|
|
|
|
|
|
using namespace __hwasan;
|
|
|
|
|
|
|
|
using __sanitizer::memory_order;
|
|
|
|
using __sanitizer::atomic_load;
|
|
|
|
using __sanitizer::atomic_store;
|
|
|
|
using __sanitizer::atomic_uintptr_t;
|
|
|
|
|
|
|
|
static uptr allocated_for_dlsym;
|
|
|
|
static const uptr kDlsymAllocPoolSize = 1024;
|
|
|
|
static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize];
|
|
|
|
|
|
|
|
static bool IsInDlsymAllocPool(const void *ptr) {
|
|
|
|
uptr off = (uptr)ptr - (uptr)alloc_memory_for_dlsym;
|
|
|
|
return off < sizeof(alloc_memory_for_dlsym);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *AllocateFromLocalPool(uptr size_in_bytes) {
|
|
|
|
uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize;
|
|
|
|
void *mem = (void *)&alloc_memory_for_dlsym[allocated_for_dlsym];
|
|
|
|
allocated_for_dlsym += size_in_words;
|
|
|
|
CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize);
|
|
|
|
return mem;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ENSURE_HWASAN_INITED() do { \
|
|
|
|
CHECK(!hwasan_init_is_running); \
|
|
|
|
if (!hwasan_inited) { \
|
|
|
|
__hwasan_init(); \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
int __sanitizer_posix_memalign(void **memptr, uptr alignment, uptr size) {
|
2017-12-09 09:31:51 +08:00
|
|
|
GET_MALLOC_STACK_TRACE;
|
|
|
|
CHECK_NE(memptr, 0);
|
|
|
|
int res = hwasan_posix_memalign(memptr, alignment, size, &stack);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
void * __sanitizer_memalign(uptr alignment, uptr size) {
|
2017-12-09 09:31:51 +08:00
|
|
|
GET_MALLOC_STACK_TRACE;
|
|
|
|
return hwasan_memalign(alignment, size, &stack);
|
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
void * __sanitizer_aligned_alloc(uptr alignment, uptr size) {
|
2017-12-09 09:31:51 +08:00
|
|
|
GET_MALLOC_STACK_TRACE;
|
|
|
|
return hwasan_aligned_alloc(alignment, size, &stack);
|
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
void * __sanitizer___libc_memalign(uptr alignment, uptr size) {
|
2017-12-09 09:31:51 +08:00
|
|
|
GET_MALLOC_STACK_TRACE;
|
|
|
|
void *ptr = hwasan_memalign(alignment, size, &stack);
|
|
|
|
if (ptr)
|
|
|
|
DTLS_on_libc_memalign(ptr, size);
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
void * __sanitizer_valloc(uptr size) {
|
2017-12-09 09:31:51 +08:00
|
|
|
GET_MALLOC_STACK_TRACE;
|
|
|
|
return hwasan_valloc(size, &stack);
|
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
void * __sanitizer_pvalloc(uptr size) {
|
2017-12-09 09:31:51 +08:00
|
|
|
GET_MALLOC_STACK_TRACE;
|
|
|
|
return hwasan_pvalloc(size, &stack);
|
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
void __sanitizer_free(void *ptr) {
|
2017-12-09 09:31:51 +08:00
|
|
|
GET_MALLOC_STACK_TRACE;
|
|
|
|
if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) return;
|
hwasan: Use system allocator to realloc and free untagged pointers in interceptor mode.
The Android dynamic loader has a non-standard feature that allows
libraries such as the hwasan runtime to interpose symbols even after
the symbol already has a value. The new value of the symbol is used to
relocate libraries loaded after the interposing library, but existing
libraries keep the old value. This behaviour is activated by the
DF_1_GLOBAL flag in DT_FLAGS_1, which is set by passing -z global to
the linker, which is what we already do to link the hwasan runtime.
What this means in practice is that if we have .so files that depend
on interceptor-mode hwasan without the main executable depending on
it, some of the libraries in the process will be using the hwasan
allocator and some will be using the system allocator, and these
allocators need to interact somehow. For example, if an instrumented
library calls a function such as strdup that allocates memory on
behalf of the caller, the instrumented library can reasonably expect
to be able to call free to deallocate the memory.
We can handle that relatively easily with hwasan by using tag 0 to
represent allocations from the system allocator. If hwasan's realloc
or free functions are passed a pointer with tag 0, the system allocator
is called.
One limitation is that this scheme doesn't work in reverse: if an
instrumented library allocates memory, it must free the memory itself
and cannot pass ownership to a system library. In a future change,
we may want to expose an API for calling the system allocator so
that instrumented libraries can safely transfer ownership of memory
to system libraries.
Differential Revision: https://reviews.llvm.org/D55986
llvm-svn: 350427
2019-01-05 03:21:51 +08:00
|
|
|
hwasan_free(ptr, &stack);
|
2017-12-09 09:31:51 +08:00
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
void __sanitizer_cfree(void *ptr) {
|
2017-12-09 09:31:51 +08:00
|
|
|
GET_MALLOC_STACK_TRACE;
|
|
|
|
if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) return;
|
hwasan: Use system allocator to realloc and free untagged pointers in interceptor mode.
The Android dynamic loader has a non-standard feature that allows
libraries such as the hwasan runtime to interpose symbols even after
the symbol already has a value. The new value of the symbol is used to
relocate libraries loaded after the interposing library, but existing
libraries keep the old value. This behaviour is activated by the
DF_1_GLOBAL flag in DT_FLAGS_1, which is set by passing -z global to
the linker, which is what we already do to link the hwasan runtime.
What this means in practice is that if we have .so files that depend
on interceptor-mode hwasan without the main executable depending on
it, some of the libraries in the process will be using the hwasan
allocator and some will be using the system allocator, and these
allocators need to interact somehow. For example, if an instrumented
library calls a function such as strdup that allocates memory on
behalf of the caller, the instrumented library can reasonably expect
to be able to call free to deallocate the memory.
We can handle that relatively easily with hwasan by using tag 0 to
represent allocations from the system allocator. If hwasan's realloc
or free functions are passed a pointer with tag 0, the system allocator
is called.
One limitation is that this scheme doesn't work in reverse: if an
instrumented library allocates memory, it must free the memory itself
and cannot pass ownership to a system library. In a future change,
we may want to expose an API for calling the system allocator so
that instrumented libraries can safely transfer ownership of memory
to system libraries.
Differential Revision: https://reviews.llvm.org/D55986
llvm-svn: 350427
2019-01-05 03:21:51 +08:00
|
|
|
hwasan_free(ptr, &stack);
|
2017-12-09 09:31:51 +08:00
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
uptr __sanitizer_malloc_usable_size(const void *ptr) {
|
2017-12-09 09:31:51 +08:00
|
|
|
return __sanitizer_get_allocated_size(ptr);
|
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
struct __sanitizer_struct_mallinfo __sanitizer_mallinfo() {
|
|
|
|
__sanitizer_struct_mallinfo sret;
|
|
|
|
internal_memset(&sret, 0, sizeof(sret));
|
|
|
|
return sret;
|
2017-12-09 09:31:51 +08:00
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
int __sanitizer_mallopt(int cmd, int value) {
|
2018-10-26 06:15:44 +08:00
|
|
|
return 0;
|
2017-12-09 09:31:51 +08:00
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
void __sanitizer_malloc_stats(void) {
|
2017-12-09 09:31:51 +08:00
|
|
|
// FIXME: implement, but don't call REAL(malloc_stats)!
|
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
void * __sanitizer_calloc(uptr nmemb, uptr size) {
|
2017-12-09 09:31:51 +08:00
|
|
|
GET_MALLOC_STACK_TRACE;
|
|
|
|
if (UNLIKELY(!hwasan_inited))
|
|
|
|
// Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
|
|
|
|
return AllocateFromLocalPool(nmemb * size);
|
|
|
|
return hwasan_calloc(nmemb, size, &stack);
|
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
void * __sanitizer_realloc(void *ptr, uptr size) {
|
2017-12-09 09:31:51 +08:00
|
|
|
GET_MALLOC_STACK_TRACE;
|
|
|
|
if (UNLIKELY(IsInDlsymAllocPool(ptr))) {
|
|
|
|
uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym;
|
|
|
|
uptr copy_size = Min(size, kDlsymAllocPoolSize - offset);
|
|
|
|
void *new_ptr;
|
|
|
|
if (UNLIKELY(!hwasan_inited)) {
|
|
|
|
new_ptr = AllocateFromLocalPool(copy_size);
|
|
|
|
} else {
|
|
|
|
copy_size = size;
|
|
|
|
new_ptr = hwasan_malloc(copy_size, &stack);
|
|
|
|
}
|
|
|
|
internal_memcpy(new_ptr, ptr, copy_size);
|
|
|
|
return new_ptr;
|
|
|
|
}
|
|
|
|
return hwasan_realloc(ptr, size, &stack);
|
|
|
|
}
|
|
|
|
|
2019-05-02 01:33:01 +08:00
|
|
|
void * __sanitizer_reallocarray(void *ptr, uptr nmemb, uptr size) {
|
|
|
|
GET_MALLOC_STACK_TRACE;
|
|
|
|
return hwasan_reallocarray(ptr, nmemb, size, &stack);
|
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
void * __sanitizer_malloc(uptr size) {
|
2017-12-09 09:31:51 +08:00
|
|
|
GET_MALLOC_STACK_TRACE;
|
[HWASan] Port HWASan to Linux x86-64 (compiler-rt)
Summary:
Porting HWASan to Linux x86-64, first of the three patches, compiler-rt part.
The approach is similar to ARM case, trap signal is used to communicate
memory tag check failure. int3 instruction is used to generate a signal,
access parameters are stored in nop [eax + offset] instruction immediately
following the int3 one
Had to add HWASan init on malloc because, due to much less interceptors
defined (most other sanitizers intercept much more and get initalized
via one of those interceptors or don't care about malloc), HWASan was not
initialized yet when libstdc++ was trying to allocate memory for its own
fixed-size heap, which led to CHECK-fail in AllocateFromLocalPool.
Also added the CHECK() failure handler with more detailed message and
stack reporting.
Reviewers: eugenis
Subscribers: kubamracek, dberris, mgorny, kristof.beyls, delcypher, #sanitizers, llvm-commits
Differential Revision: https://reviews.llvm.org/D44705
llvm-svn: 328385
2018-03-24 07:38:04 +08:00
|
|
|
if (UNLIKELY(!hwasan_init_is_running))
|
|
|
|
ENSURE_HWASAN_INITED();
|
2017-12-09 09:31:51 +08:00
|
|
|
if (UNLIKELY(!hwasan_inited))
|
|
|
|
// Hack: dlsym calls malloc before REAL(malloc) is retrieved from dlsym.
|
|
|
|
return AllocateFromLocalPool(size);
|
|
|
|
return hwasan_malloc(size, &stack);
|
|
|
|
}
|
|
|
|
|
2018-09-07 06:53:08 +08:00
|
|
|
#if HWASAN_WITH_INTERCEPTORS
|
2018-09-21 03:30:51 +08:00
|
|
|
#define INTERCEPTOR_ALIAS(RET, FN, ARGS...) \
|
|
|
|
extern "C" SANITIZER_INTERFACE_ATTRIBUTE RET WRAP(FN)(ARGS) \
|
|
|
|
ALIAS("__sanitizer_" #FN); \
|
|
|
|
extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE RET FN( \
|
|
|
|
ARGS) ALIAS("__sanitizer_" #FN)
|
2018-09-07 06:53:08 +08:00
|
|
|
|
|
|
|
INTERCEPTOR_ALIAS(int, posix_memalign, void **memptr, SIZE_T alignment,
|
|
|
|
SIZE_T size);
|
|
|
|
INTERCEPTOR_ALIAS(void *, aligned_alloc, SIZE_T alignment, SIZE_T size);
|
|
|
|
INTERCEPTOR_ALIAS(void *, __libc_memalign, SIZE_T alignment, SIZE_T size);
|
|
|
|
INTERCEPTOR_ALIAS(void *, valloc, SIZE_T size);
|
|
|
|
INTERCEPTOR_ALIAS(void, free, void *ptr);
|
|
|
|
INTERCEPTOR_ALIAS(uptr, malloc_usable_size, const void *ptr);
|
|
|
|
INTERCEPTOR_ALIAS(void *, calloc, SIZE_T nmemb, SIZE_T size);
|
|
|
|
INTERCEPTOR_ALIAS(void *, realloc, void *ptr, SIZE_T size);
|
2019-05-02 01:33:01 +08:00
|
|
|
INTERCEPTOR_ALIAS(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size);
|
2018-09-07 06:53:08 +08:00
|
|
|
INTERCEPTOR_ALIAS(void *, malloc, SIZE_T size);
|
|
|
|
|
|
|
|
#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
|
|
|
|
INTERCEPTOR_ALIAS(void *, memalign, SIZE_T alignment, SIZE_T size);
|
|
|
|
INTERCEPTOR_ALIAS(void *, pvalloc, SIZE_T size);
|
|
|
|
INTERCEPTOR_ALIAS(void, cfree, void *ptr);
|
|
|
|
INTERCEPTOR_ALIAS(__sanitizer_struct_mallinfo, mallinfo);
|
|
|
|
INTERCEPTOR_ALIAS(int, mallopt, int cmd, int value);
|
|
|
|
INTERCEPTOR_ALIAS(void, malloc_stats, void);
|
|
|
|
#endif
|
|
|
|
|
2019-11-04 18:58:46 +08:00
|
|
|
struct ThreadStartArg {
|
|
|
|
thread_callback_t callback;
|
|
|
|
void *param;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void *HwasanThreadStartFunc(void *arg) {
|
|
|
|
__hwasan_thread_enter();
|
|
|
|
ThreadStartArg A = *reinterpret_cast<ThreadStartArg*>(arg);
|
|
|
|
UnmapOrDie(arg, GetPageSizeCached());
|
|
|
|
return A.callback(A.param);
|
|
|
|
}
|
2019-01-05 07:24:02 +08:00
|
|
|
|
2019-11-04 18:58:46 +08:00
|
|
|
INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
|
|
|
|
void * param) {
|
2019-01-05 07:24:02 +08:00
|
|
|
ScopedTaggingDisabler disabler;
|
2019-11-04 18:58:46 +08:00
|
|
|
ThreadStartArg *A = reinterpret_cast<ThreadStartArg *> (MmapOrDie(
|
|
|
|
GetPageSizeCached(), "pthread_create"));
|
|
|
|
*A = {callback, param};
|
2019-01-05 07:24:02 +08:00
|
|
|
int res = REAL(pthread_create)(UntagPtr(th), UntagPtr(attr),
|
2019-11-04 18:58:46 +08:00
|
|
|
&HwasanThreadStartFunc, A);
|
2019-01-05 07:24:02 +08:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2019-05-10 22:15:13 +08:00
|
|
|
DEFINE_REAL(int, vfork)
|
|
|
|
DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork)
|
2019-11-04 18:58:46 +08:00
|
|
|
#endif // HWASAN_WITH_INTERCEPTORS
|
[hwasan, asan] Intercept vfork.
Summary:
Intercept vfork on arm, aarch64, i386 and x86_64.
Reviewers: pcc, vitalybuka
Subscribers: kubamracek, mgorny, javed.absar, krytarowski, kristof.beyls, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D58533
llvm-svn: 355030
2019-02-28 05:11:50 +08:00
|
|
|
|
2019-10-30 22:04:40 +08:00
|
|
|
#if HWASAN_WITH_INTERCEPTORS && defined(__aarch64__)
|
|
|
|
// Get and/or change the set of blocked signals.
|
|
|
|
extern "C" int sigprocmask(int __how, const __hw_sigset_t *__restrict __set,
|
|
|
|
__hw_sigset_t *__restrict __oset);
|
|
|
|
#define SIG_BLOCK 0
|
|
|
|
#define SIG_SETMASK 2
|
|
|
|
extern "C" int __sigjmp_save(__hw_sigjmp_buf env, int savemask) {
|
|
|
|
env[0].__mask_was_saved =
|
|
|
|
(savemask && sigprocmask(SIG_BLOCK, (__hw_sigset_t *)0,
|
|
|
|
&env[0].__saved_mask) == 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __attribute__((always_inline))
|
|
|
|
InternalLongjmp(__hw_register_buf env, int retval) {
|
|
|
|
// Clear all memory tags on the stack between here and where we're going.
|
|
|
|
unsigned long long stack_pointer = env[13];
|
|
|
|
// The stack pointer should never be tagged, so we don't need to clear the
|
|
|
|
// tag for this function call.
|
|
|
|
__hwasan_handle_longjmp((void *)stack_pointer);
|
|
|
|
|
|
|
|
// Run code for handling a longjmp.
|
|
|
|
// Need to use a register that isn't going to be loaded from the environment
|
|
|
|
// buffer -- hence why we need to specify the register to use.
|
|
|
|
// Must implement this ourselves, since we don't know the order of registers
|
|
|
|
// in different libc implementations and many implementations mangle the
|
|
|
|
// stack pointer so we can't use it without knowing the demangling scheme.
|
|
|
|
register long int retval_tmp asm("x1") = retval;
|
|
|
|
register void *env_address asm("x0") = &env[0];
|
|
|
|
asm volatile("ldp x19, x20, [%0, #0<<3];"
|
|
|
|
"ldp x21, x22, [%0, #2<<3];"
|
|
|
|
"ldp x23, x24, [%0, #4<<3];"
|
|
|
|
"ldp x25, x26, [%0, #6<<3];"
|
|
|
|
"ldp x27, x28, [%0, #8<<3];"
|
|
|
|
"ldp x29, x30, [%0, #10<<3];"
|
|
|
|
"ldp d8, d9, [%0, #14<<3];"
|
|
|
|
"ldp d10, d11, [%0, #16<<3];"
|
|
|
|
"ldp d12, d13, [%0, #18<<3];"
|
|
|
|
"ldp d14, d15, [%0, #20<<3];"
|
|
|
|
"ldr x5, [%0, #13<<3];"
|
|
|
|
"mov sp, x5;"
|
|
|
|
// Return the value requested to return through arguments.
|
|
|
|
// This should be in x1 given what we requested above.
|
|
|
|
"cmp %1, #0;"
|
|
|
|
"mov x0, #1;"
|
|
|
|
"csel x0, %1, x0, ne;"
|
|
|
|
"br x30;"
|
|
|
|
: "+r"(env_address)
|
|
|
|
: "r"(retval_tmp));
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(void, siglongjmp, __hw_sigjmp_buf env, int val) {
|
|
|
|
if (env[0].__mask_was_saved)
|
|
|
|
// Restore the saved signal mask.
|
|
|
|
(void)sigprocmask(SIG_SETMASK, &env[0].__saved_mask,
|
|
|
|
(__hw_sigset_t *)0);
|
|
|
|
InternalLongjmp(env[0].__jmpbuf, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Required since glibc libpthread calls __libc_longjmp on pthread_exit, and
|
|
|
|
// _setjmp on start_thread. Hence we have to intercept the longjmp on
|
|
|
|
// pthread_exit so the __hw_jmp_buf order matches.
|
|
|
|
INTERCEPTOR(void, __libc_longjmp, __hw_jmp_buf env, int val) {
|
|
|
|
InternalLongjmp(env[0].__jmpbuf, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(void, longjmp, __hw_jmp_buf env, int val) {
|
|
|
|
InternalLongjmp(env[0].__jmpbuf, val);
|
|
|
|
}
|
|
|
|
#undef SIG_BLOCK
|
|
|
|
#undef SIG_SETMASK
|
|
|
|
|
|
|
|
#endif // HWASAN_WITH_INTERCEPTORS && __aarch64__
|
|
|
|
|
2017-12-09 09:31:51 +08:00
|
|
|
static void BeforeFork() {
|
|
|
|
StackDepotLockAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void AfterFork() {
|
|
|
|
StackDepotUnlockAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERCEPTOR(int, fork, void) {
|
|
|
|
ENSURE_HWASAN_INITED();
|
|
|
|
BeforeFork();
|
|
|
|
int pid = REAL(fork)();
|
|
|
|
AfterFork();
|
|
|
|
return pid;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace __hwasan {
|
|
|
|
|
|
|
|
int OnExit() {
|
|
|
|
// FIXME: ask frontend whether we need to return failure.
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace __hwasan
|
|
|
|
|
|
|
|
namespace __hwasan {
|
|
|
|
|
|
|
|
void InitializeInterceptors() {
|
|
|
|
static int inited = 0;
|
|
|
|
CHECK_EQ(inited, 0);
|
|
|
|
|
|
|
|
INTERCEPT_FUNCTION(fork);
|
|
|
|
|
[hwasan] Add a (almost) no-interceptor mode.
Summary:
The idea behind this change is to allow sanitization of libc. We are prototyping on Bionic,
but the tool interface will be general enough (or at least generalizable) to support any other libc.
When libc depends on libclang_rt.hwasan, the latter can not interpose libc functions.
In fact, majority of interceptors become unnecessary when libc code is instrumented.
This change gets rid of most hwasan interceptors and provides interface for libc to notify
hwasan about thread creation and destruction events. Some interceptors (pthread_create)
are kept under #ifdef to enable testing with uninstrumented libc. They are expressed in
terms of the new libc interface.
The new cmake switch, COMPILER_RT_HWASAN_WITH_INTERCEPTORS, ON by default, builds testing
version of the library with the aforementioned pthread_create interceptor.
With the OFF setting, the library becomes more of a libc plugin.
Reviewers: vitalybuka, kcc, jfb
Subscribers: srhines, kubamracek, mgorny, jfb, llvm-commits
Differential Revision: https://reviews.llvm.org/D50922
llvm-svn: 340216
2018-08-21 05:49:15 +08:00
|
|
|
#if HWASAN_WITH_INTERCEPTORS
|
[hwasan, asan] Intercept vfork.
Summary:
Intercept vfork on arm, aarch64, i386 and x86_64.
Reviewers: pcc, vitalybuka
Subscribers: kubamracek, mgorny, javed.absar, krytarowski, kristof.beyls, #sanitizers, llvm-commits
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D58533
llvm-svn: 355030
2019-02-28 05:11:50 +08:00
|
|
|
#if defined(__linux__)
|
|
|
|
INTERCEPT_FUNCTION(vfork);
|
|
|
|
#endif // __linux__
|
2019-01-05 07:24:02 +08:00
|
|
|
INTERCEPT_FUNCTION(pthread_create);
|
[hwasan] Add a (almost) no-interceptor mode.
Summary:
The idea behind this change is to allow sanitization of libc. We are prototyping on Bionic,
but the tool interface will be general enough (or at least generalizable) to support any other libc.
When libc depends on libclang_rt.hwasan, the latter can not interpose libc functions.
In fact, majority of interceptors become unnecessary when libc code is instrumented.
This change gets rid of most hwasan interceptors and provides interface for libc to notify
hwasan about thread creation and destruction events. Some interceptors (pthread_create)
are kept under #ifdef to enable testing with uninstrumented libc. They are expressed in
terms of the new libc interface.
The new cmake switch, COMPILER_RT_HWASAN_WITH_INTERCEPTORS, ON by default, builds testing
version of the library with the aforementioned pthread_create interceptor.
With the OFF setting, the library becomes more of a libc plugin.
Reviewers: vitalybuka, kcc, jfb
Subscribers: srhines, kubamracek, mgorny, jfb, llvm-commits
Differential Revision: https://reviews.llvm.org/D50922
llvm-svn: 340216
2018-08-21 05:49:15 +08:00
|
|
|
#endif
|
|
|
|
|
2017-12-09 09:31:51 +08:00
|
|
|
inited = 1;
|
|
|
|
}
|
|
|
|
} // namespace __hwasan
|