diff --git a/compiler-rt/lib/gwp_asan/CMakeLists.txt b/compiler-rt/lib/gwp_asan/CMakeLists.txt --- a/compiler-rt/lib/gwp_asan/CMakeLists.txt +++ b/compiler-rt/lib/gwp_asan/CMakeLists.txt @@ -22,6 +22,8 @@ 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 diff --git a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h --- a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h +++ b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.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 @@ // 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; } diff --git a/compiler-rt/lib/gwp_asan/platform_specific/common_fuchsia.cpp b/compiler-rt/lib/gwp_asan/platform_specific/common_fuchsia.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/gwp_asan/platform_specific/common_fuchsia.cpp @@ -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 diff --git a/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h b/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.h @@ -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 + +namespace gwp_asan { +struct PlatformSpecificMapData { + zx_handle_t Vmar; +}; +} // namespace gwp_asan + +#endif // GWP_ASAN_GUARDED_POOL_ALLOCATOR_FUCHSIA_H_ +#endif // defined(__Fuchsia__) diff --git a/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.cpp b/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.cpp @@ -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 +#include +#include +#include +#include +#include + +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(Addr); +} + +void GuardedPoolAllocator::unmap(void *Ptr, size_t Size) const { + assert((reinterpret_cast(Ptr) % State.PageSize) == 0); + assert((Size % State.PageSize) == 0); + zx_status_t Status = _zx_vmar_unmap(_zx_vmar_root_self(), + reinterpret_cast(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(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(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(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(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(Ptr), Size); + Check(Status == ZX_OK, "Vmar unmapping failed"); +} + +size_t GuardedPoolAllocator::getPlatformPageSize() { return ZX_PAGE_SIZE; } + +void GuardedPoolAllocator::installAtFork() {} +} // namespace gwp_asan diff --git a/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.h b/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.h new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.h @@ -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__) diff --git a/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_tls.h b/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_tls.h --- a/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_tls.h +++ b/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_tls.h @@ -39,15 +39,17 @@ }; 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_ diff --git a/compiler-rt/lib/gwp_asan/platform_specific/utilities_fuchsia.cpp b/compiler-rt/lib/gwp_asan/platform_specific/utilities_fuchsia.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/gwp_asan/platform_specific/utilities_fuchsia.cpp @@ -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 +#include + +namespace gwp_asan { +void die(const char *Message) { + __sanitizer_log_write(Message, strlen(Message)); + __builtin_trap(); +} +} // namespace gwp_asan