2018-06-08 07:33:33 +08:00
|
|
|
//===-- hwasan_new_delete.cc ----------------------------------------------===//
|
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 operators new and delete.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "hwasan.h"
|
|
|
|
#include "interception/interception.h"
|
|
|
|
#include "sanitizer_common/sanitizer_allocator.h"
|
2018-06-08 07:33:33 +08:00
|
|
|
#include "sanitizer_common/sanitizer_allocator_report.h"
|
2017-12-09 09:31:51 +08:00
|
|
|
|
|
|
|
#if HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
using namespace __hwasan; // NOLINT
|
|
|
|
|
|
|
|
// Fake std::nothrow_t to avoid including <new>.
|
|
|
|
namespace std {
|
|
|
|
struct nothrow_t {};
|
|
|
|
} // namespace std
|
|
|
|
|
|
|
|
|
|
|
|
// TODO(alekseys): throw std::bad_alloc instead of dying on OOM.
|
|
|
|
#define OPERATOR_NEW_BODY(nothrow) \
|
|
|
|
GET_MALLOC_STACK_TRACE; \
|
|
|
|
void *res = hwasan_malloc(size, &stack);\
|
2018-06-08 07:33:33 +08:00
|
|
|
if (!nothrow && UNLIKELY(!res)) ReportOutOfMemory(size, &stack);\
|
2017-12-09 09:31:51 +08:00
|
|
|
return res
|
|
|
|
|
|
|
|
INTERCEPTOR_ATTRIBUTE
|
|
|
|
void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
|
|
|
|
INTERCEPTOR_ATTRIBUTE
|
|
|
|
void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); }
|
|
|
|
INTERCEPTOR_ATTRIBUTE
|
|
|
|
void *operator new(size_t size, std::nothrow_t const&) {
|
|
|
|
OPERATOR_NEW_BODY(true /*nothrow*/);
|
|
|
|
}
|
|
|
|
INTERCEPTOR_ATTRIBUTE
|
|
|
|
void *operator new[](size_t size, std::nothrow_t const&) {
|
|
|
|
OPERATOR_NEW_BODY(true /*nothrow*/);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define OPERATOR_DELETE_BODY \
|
|
|
|
GET_MALLOC_STACK_TRACE; \
|
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
|
|
|
if (ptr) hwasan_free(ptr, &stack)
|
2017-12-09 09:31:51 +08:00
|
|
|
|
|
|
|
INTERCEPTOR_ATTRIBUTE
|
|
|
|
void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
|
|
|
|
INTERCEPTOR_ATTRIBUTE
|
|
|
|
void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; }
|
|
|
|
INTERCEPTOR_ATTRIBUTE
|
|
|
|
void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; }
|
|
|
|
INTERCEPTOR_ATTRIBUTE
|
|
|
|
void operator delete[](void *ptr, std::nothrow_t const&) {
|
|
|
|
OPERATOR_DELETE_BODY;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // HWASAN_REPLACE_OPERATORS_NEW_AND_DELETE
|