1 //===-- guarded_pool_allocator_fuchsia.cpp ----------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "gwp_asan/guarded_pool_allocator.h" 10 #include "gwp_asan/utilities.h" 11 12 #include <assert.h> 13 #include <stdint.h> 14 #include <string.h> 15 #include <zircon/process.h> 16 #include <zircon/syscalls.h> 17 18 namespace gwp_asan { 19 void GuardedPoolAllocator::initPRNG() { 20 _zx_cprng_draw(&getThreadLocals()->RandomState, sizeof(uint32_t)); 21 } 22 23 void *GuardedPoolAllocator::map(size_t Size, const char *Name) const { 24 assert((Size % State.PageSize) == 0); 25 zx_handle_t Vmo; 26 zx_status_t Status = _zx_vmo_create(Size, 0, &Vmo); 27 checkWithErrorCode(Status == ZX_OK, "Failed to create Vmo", Status); 28 _zx_object_set_property(Vmo, ZX_PROP_NAME, Name, strlen(Name)); 29 zx_vaddr_t Addr; 30 Status = _zx_vmar_map(_zx_vmar_root_self(), 31 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | ZX_VM_ALLOW_FAULTS, 32 0, Vmo, 0, Size, &Addr); 33 checkWithErrorCode(Status == ZX_OK, "Vmo mapping failed", Status); 34 _zx_handle_close(Vmo); 35 return reinterpret_cast<void *>(Addr); 36 } 37 38 void GuardedPoolAllocator::unmap(void *Ptr, size_t Size) const { 39 assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0); 40 assert((Size % State.PageSize) == 0); 41 zx_status_t Status = _zx_vmar_unmap(_zx_vmar_root_self(), 42 reinterpret_cast<zx_vaddr_t>(Ptr), Size); 43 checkWithErrorCode(Status == ZX_OK, "Vmo unmapping failed", Status); 44 } 45 46 void *GuardedPoolAllocator::reserveGuardedPool(size_t Size) { 47 assert((Size % State.PageSize) == 0); 48 zx_vaddr_t Addr; 49 const zx_status_t Status = _zx_vmar_allocate( 50 _zx_vmar_root_self(), 51 ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE | ZX_VM_CAN_MAP_SPECIFIC, 0, 52 Size, &GuardedPagePoolPlatformData.Vmar, &Addr); 53 checkWithErrorCode(Status == ZX_OK, 54 "Failed to reserve guarded pool allocator memory", Status); 55 _zx_object_set_property(GuardedPagePoolPlatformData.Vmar, ZX_PROP_NAME, 56 kGwpAsanGuardPageName, strlen(kGwpAsanGuardPageName)); 57 return reinterpret_cast<void *>(Addr); 58 } 59 60 void GuardedPoolAllocator::unreserveGuardedPool() { 61 const zx_handle_t Vmar = GuardedPagePoolPlatformData.Vmar; 62 assert(Vmar != ZX_HANDLE_INVALID && Vmar != _zx_vmar_root_self()); 63 zx_status_t Status = _zx_vmar_destroy(Vmar); 64 checkWithErrorCode(Status == ZX_OK, "Failed to destroy a vmar", Status); 65 Status = _zx_handle_close(Vmar); 66 checkWithErrorCode(Status == ZX_OK, "Failed to close a vmar", Status); 67 GuardedPagePoolPlatformData.Vmar = ZX_HANDLE_INVALID; 68 } 69 70 void GuardedPoolAllocator::allocateInGuardedPool(void *Ptr, size_t Size) const { 71 assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0); 72 assert((Size % State.PageSize) == 0); 73 zx_handle_t Vmo; 74 zx_status_t Status = _zx_vmo_create(Size, 0, &Vmo); 75 checkWithErrorCode(Status == ZX_OK, "Failed to create vmo", Status); 76 _zx_object_set_property(Vmo, ZX_PROP_NAME, kGwpAsanAliveSlotName, 77 strlen(kGwpAsanAliveSlotName)); 78 const zx_handle_t Vmar = GuardedPagePoolPlatformData.Vmar; 79 assert(Vmar != ZX_HANDLE_INVALID && Vmar != _zx_vmar_root_self()); 80 const size_t Offset = 81 reinterpret_cast<uintptr_t>(Ptr) - State.GuardedPagePool; 82 zx_vaddr_t P; 83 Status = _zx_vmar_map(Vmar, 84 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE | 85 ZX_VM_ALLOW_FAULTS | ZX_VM_SPECIFIC, 86 Offset, Vmo, 0, Size, &P); 87 checkWithErrorCode(Status == ZX_OK, "Vmo mapping failed", Status); 88 _zx_handle_close(Vmo); 89 } 90 91 void GuardedPoolAllocator::deallocateInGuardedPool(void *Ptr, 92 size_t Size) const { 93 assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0); 94 assert((Size % State.PageSize) == 0); 95 const zx_handle_t Vmar = GuardedPagePoolPlatformData.Vmar; 96 assert(Vmar != ZX_HANDLE_INVALID && Vmar != _zx_vmar_root_self()); 97 const zx_status_t Status = 98 _zx_vmar_unmap(Vmar, reinterpret_cast<zx_vaddr_t>(Ptr), Size); 99 checkWithErrorCode(Status == ZX_OK, "Vmar unmapping failed", Status); 100 } 101 102 size_t GuardedPoolAllocator::getPlatformPageSize() { 103 return _zx_system_get_page_size(); 104 } 105 106 void GuardedPoolAllocator::installAtFork() {} 107 } // namespace gwp_asan 108