[GWP-ASan] Fuchsia specific mapping & utilities functions
This CL introduces the Fuchsia versions of the existing platform specific functions. For Fuchsia, we need to track the VMAR (https://fuchsia.dev/fuchsia-src/reference/kernel_objects/vm_address_region) of the Guarded Pool mapping, and for this purpose I added some platform specific data structure that remains empty on POSIX platforms. `getThreadID` is not super useful for Fuchsia so it's just left as a stub for now. While testing the changes in my Fuchsia tree, I realized that `guarded_pool_allocator_tls.h` should have closed the namespace before including `GWP_ASAN_PLATFORM_TLS_HEADER`, otherwise drama ensues. This was tested in g3, upstream LLVM, and Fuchsia (with local changes). Differential Revision: https://reviews.llvm.org/D90483
This commit is contained in:
parent
799033d8c5
commit
63ad087656
|
@ -22,6 +22,8 @@ set(GWP_ASAN_HEADERS
|
|||
mutex.h
|
||||
options.h
|
||||
options.inc
|
||||
platform_specific/guarded_pool_allocator_fuchsia.h
|
||||
platform_specific/guarded_pool_allocator_posix.h
|
||||
platform_specific/guarded_pool_allocator_tls.h
|
||||
platform_specific/mutex_fuchsia.h
|
||||
platform_specific/mutex_posix.h
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include "gwp_asan/definitions.h"
|
||||
#include "gwp_asan/mutex.h"
|
||||
#include "gwp_asan/options.h"
|
||||
#include "gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h"
|
||||
#include "gwp_asan/platform_specific/guarded_pool_allocator_posix.h"
|
||||
#include "gwp_asan/platform_specific/guarded_pool_allocator_tls.h"
|
||||
#include "gwp_asan/stack_trace_compressor.h"
|
||||
|
||||
|
@ -207,6 +209,9 @@ private:
|
|||
// the sample rate.
|
||||
uint32_t AdjustedSampleRatePlusOne = 0;
|
||||
|
||||
// Additional platform specific data structure for the guarded pool mapping.
|
||||
PlatformSpecificMapData GuardedPagePoolPlatformData = {};
|
||||
|
||||
class ScopedRecursiveGuard {
|
||||
public:
|
||||
ScopedRecursiveGuard() { getThreadLocals()->RecursiveGuard = true; }
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
//===-- common_fuchsia.cpp --------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gwp_asan/common.h"
|
||||
|
||||
namespace gwp_asan {
|
||||
// This is only used for AllocationTrace.ThreadID and allocation traces are not
|
||||
// yet supported on Fuchsia.
|
||||
uint64_t getThreadID() { return kInvalidThreadID; }
|
||||
} // namespace gwp_asan
|
|
@ -0,0 +1,103 @@
|
|||
//===-- guarded_pool_allocator_fuchsia.cpp ----------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gwp_asan/guarded_pool_allocator.h"
|
||||
#include "gwp_asan/utilities.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <zircon/limits.h>
|
||||
#include <zircon/process.h>
|
||||
#include <zircon/syscalls.h>
|
||||
|
||||
namespace gwp_asan {
|
||||
void GuardedPoolAllocator::initPRNG() {
|
||||
_zx_cprng_draw(&getThreadLocals()->RandomState, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void *GuardedPoolAllocator::map(size_t Size, const char *Name) const {
|
||||
assert((Size % State.PageSize) == 0);
|
||||
zx_handle_t Vmo;
|
||||
zx_status_t Status = _zx_vmo_create(Size, 0, &Vmo);
|
||||
Check(Status == ZX_OK, "Failed to create Vmo");
|
||||
_zx_object_set_property(Vmo, ZX_PROP_NAME, Name, strlen(Name));
|
||||
zx_vaddr_t Addr;
|
||||
Status = _zx_vmar_map(_zx_vmar_root_self(),
|
||||
ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_ALLOW_FAULTS,
|
||||
0, Vmo, 0, Size, &Addr);
|
||||
Check(Status == ZX_OK, "Vmo mapping failed");
|
||||
_zx_handle_close(Vmo);
|
||||
return reinterpret_cast<void *>(Addr);
|
||||
}
|
||||
|
||||
void GuardedPoolAllocator::unmap(void *Ptr, size_t Size) const {
|
||||
assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
|
||||
assert((Size % State.PageSize) == 0);
|
||||
zx_status_t Status = _zx_vmar_unmap(_zx_vmar_root_self(),
|
||||
reinterpret_cast<zx_vaddr_t>(Ptr), Size);
|
||||
Check(Status == ZX_OK, "Vmo unmapping failed");
|
||||
}
|
||||
|
||||
void *GuardedPoolAllocator::reserveGuardedPool(size_t Size) {
|
||||
assert((Size % State.PageSize) == 0);
|
||||
zx_vaddr_t Addr;
|
||||
const zx_status_t Status = _zx_vmar_allocate(
|
||||
_zx_vmar_root_self(),
|
||||
ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE | ZX_VM_CAN_MAP_SPECIFIC, 0,
|
||||
Size, &GuardedPagePoolPlatformData.Vmar, &Addr);
|
||||
Check(Status == ZX_OK, "Failed to reserve guarded pool allocator memory");
|
||||
_zx_object_set_property(GuardedPagePoolPlatformData.Vmar, ZX_PROP_NAME,
|
||||
kGwpAsanGuardPageName, strlen(kGwpAsanGuardPageName));
|
||||
return reinterpret_cast<void *>(Addr);
|
||||
}
|
||||
|
||||
void GuardedPoolAllocator::unreserveGuardedPool() {
|
||||
const zx_handle_t Vmar = GuardedPagePoolPlatformData.Vmar;
|
||||
assert(Vmar != ZX_HANDLE_INVALID && Vmar != _zx_vmar_root_self());
|
||||
Check(_zx_vmar_destroy(Vmar) == ZX_OK, "Failed to destroy a vmar");
|
||||
Check(_zx_handle_close(Vmar) == ZX_OK, "Failed to close a vmar");
|
||||
GuardedPagePoolPlatformData.Vmar = ZX_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
void GuardedPoolAllocator::allocateInGuardedPool(void *Ptr, size_t Size) const {
|
||||
assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
|
||||
assert((Size % State.PageSize) == 0);
|
||||
zx_handle_t Vmo;
|
||||
zx_status_t Status = _zx_vmo_create(Size, 0, &Vmo);
|
||||
Check(Status == ZX_OK, "Failed to create vmo");
|
||||
_zx_object_set_property(Vmo, ZX_PROP_NAME, kGwpAsanAliveSlotName,
|
||||
strlen(kGwpAsanAliveSlotName));
|
||||
const zx_handle_t Vmar = GuardedPagePoolPlatformData.Vmar;
|
||||
assert(Vmar != ZX_HANDLE_INVALID && Vmar != _zx_vmar_root_self());
|
||||
const size_t Offset =
|
||||
reinterpret_cast<uintptr_t>(Ptr) - State.GuardedPagePool;
|
||||
zx_vaddr_t P;
|
||||
Status = _zx_vmar_map(Vmar,
|
||||
ZX_VM_PERM_READ | ZX_VM_PERM_WRITE |
|
||||
ZX_VM_ALLOW_FAULTS | ZX_VM_SPECIFIC,
|
||||
Offset, Vmo, 0, Size, &P);
|
||||
Check(Status == ZX_OK, "Vmo mapping failed");
|
||||
_zx_handle_close(Vmo);
|
||||
}
|
||||
|
||||
void GuardedPoolAllocator::deallocateInGuardedPool(void *Ptr,
|
||||
size_t Size) const {
|
||||
assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
|
||||
assert((Size % State.PageSize) == 0);
|
||||
const zx_handle_t Vmar = GuardedPagePoolPlatformData.Vmar;
|
||||
assert(Vmar != ZX_HANDLE_INVALID && Vmar != _zx_vmar_root_self());
|
||||
const zx_status_t Status =
|
||||
_zx_vmar_unmap(Vmar, reinterpret_cast<zx_vaddr_t>(Ptr), Size);
|
||||
Check(Status == ZX_OK, "Vmar unmapping failed");
|
||||
}
|
||||
|
||||
size_t GuardedPoolAllocator::getPlatformPageSize() { return ZX_PAGE_SIZE; }
|
||||
|
||||
void GuardedPoolAllocator::installAtFork() {}
|
||||
} // namespace gwp_asan
|
|
@ -0,0 +1,22 @@
|
|||
//===-- guarded_pool_allocator_fuchsia.h ------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if defined(__Fuchsia__)
|
||||
#ifndef GWP_ASAN_GUARDED_POOL_ALLOCATOR_FUCHSIA_H_
|
||||
#define GWP_ASAN_GUARDED_POOL_ALLOCATOR_FUCHSIA_H_
|
||||
|
||||
#include <zircon/types.h>
|
||||
|
||||
namespace gwp_asan {
|
||||
struct PlatformSpecificMapData {
|
||||
zx_handle_t Vmar;
|
||||
};
|
||||
} // namespace gwp_asan
|
||||
|
||||
#endif // GWP_ASAN_GUARDED_POOL_ALLOCATOR_FUCHSIA_H_
|
||||
#endif // defined(__Fuchsia__)
|
|
@ -0,0 +1,18 @@
|
|||
//===-- guarded_pool_allocator_posix.h --------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if defined(__unix__)
|
||||
#ifndef GWP_ASAN_GUARDED_POOL_ALLOCATOR_POSIX_H_
|
||||
#define GWP_ASAN_GUARDED_POOL_ALLOCATOR_POSIX_H_
|
||||
|
||||
namespace gwp_asan {
|
||||
struct PlatformSpecificMapData {};
|
||||
} // namespace gwp_asan
|
||||
|
||||
#endif // GWP_ASAN_GUARDED_POOL_ALLOCATOR_POSIX_H_
|
||||
#endif // defined(__unix__)
|
|
@ -39,15 +39,17 @@ struct ThreadLocalPackedVariables {
|
|||
};
|
||||
static_assert(sizeof(ThreadLocalPackedVariables) == sizeof(uint64_t),
|
||||
"thread local data does not fit in a uint64_t");
|
||||
} // namespace gwp_asan
|
||||
|
||||
#ifdef GWP_ASAN_PLATFORM_TLS_HEADER
|
||||
#include GWP_ASAN_PLATFORM_TLS_HEADER
|
||||
#else
|
||||
namespace gwp_asan {
|
||||
inline ThreadLocalPackedVariables *getThreadLocals() {
|
||||
alignas(8) static GWP_ASAN_TLS_INITIAL_EXEC ThreadLocalPackedVariables Locals;
|
||||
return &Locals;
|
||||
}
|
||||
#endif
|
||||
} // namespace gwp_asan
|
||||
#endif // GWP_ASAN_PLATFORM_TLS_HEADER
|
||||
|
||||
#endif // GWP_ASAN_GUARDED_POOL_ALLOCATOR_TLS_H_
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
//===-- utilities_fuchsia.cpp -----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "gwp_asan/utilities.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <zircon/sanitizer.h>
|
||||
|
||||
namespace gwp_asan {
|
||||
void die(const char *Message) {
|
||||
__sanitizer_log_write(Message, strlen(Message));
|
||||
__builtin_trap();
|
||||
}
|
||||
} // namespace gwp_asan
|
Loading…
Reference in New Issue