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 {
initPRNG()19 void GuardedPoolAllocator::initPRNG() {
20 _zx_cprng_draw(&getThreadLocals()->RandomState, sizeof(uint32_t));
21 }
22
map(size_t Size,const char * Name) const23 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 Check(Status == ZX_OK, "Failed to create Vmo");
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 Check(Status == ZX_OK, "Vmo mapping failed");
34 _zx_handle_close(Vmo);
35 return reinterpret_cast<void *>(Addr);
36 }
37
unmap(void * Ptr,size_t Size) const38 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 Check(Status == ZX_OK, "Vmo unmapping failed");
44 }
45
reserveGuardedPool(size_t Size)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 Check(Status == ZX_OK, "Failed to reserve guarded pool allocator memory");
54 _zx_object_set_property(GuardedPagePoolPlatformData.Vmar, ZX_PROP_NAME,
55 kGwpAsanGuardPageName, strlen(kGwpAsanGuardPageName));
56 return reinterpret_cast<void *>(Addr);
57 }
58
unreserveGuardedPool()59 void GuardedPoolAllocator::unreserveGuardedPool() {
60 const zx_handle_t Vmar = GuardedPagePoolPlatformData.Vmar;
61 assert(Vmar != ZX_HANDLE_INVALID && Vmar != _zx_vmar_root_self());
62 Check(_zx_vmar_destroy(Vmar) == ZX_OK, "Failed to destroy a vmar");
63 Check(_zx_handle_close(Vmar) == ZX_OK, "Failed to close a vmar");
64 GuardedPagePoolPlatformData.Vmar = ZX_HANDLE_INVALID;
65 }
66
allocateInGuardedPool(void * Ptr,size_t Size) const67 void GuardedPoolAllocator::allocateInGuardedPool(void *Ptr, size_t Size) const {
68 assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
69 assert((Size % State.PageSize) == 0);
70 zx_handle_t Vmo;
71 zx_status_t Status = _zx_vmo_create(Size, 0, &Vmo);
72 Check(Status == ZX_OK, "Failed to create vmo");
73 _zx_object_set_property(Vmo, ZX_PROP_NAME, kGwpAsanAliveSlotName,
74 strlen(kGwpAsanAliveSlotName));
75 const zx_handle_t Vmar = GuardedPagePoolPlatformData.Vmar;
76 assert(Vmar != ZX_HANDLE_INVALID && Vmar != _zx_vmar_root_self());
77 const size_t Offset =
78 reinterpret_cast<uintptr_t>(Ptr) - State.GuardedPagePool;
79 zx_vaddr_t P;
80 Status = _zx_vmar_map(Vmar,
81 ZX_VM_PERM_READ | ZX_VM_PERM_WRITE |
82 ZX_VM_ALLOW_FAULTS | ZX_VM_SPECIFIC,
83 Offset, Vmo, 0, Size, &P);
84 Check(Status == ZX_OK, "Vmo mapping failed");
85 _zx_handle_close(Vmo);
86 }
87
deallocateInGuardedPool(void * Ptr,size_t Size) const88 void GuardedPoolAllocator::deallocateInGuardedPool(void *Ptr,
89 size_t Size) const {
90 assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
91 assert((Size % State.PageSize) == 0);
92 const zx_handle_t Vmar = GuardedPagePoolPlatformData.Vmar;
93 assert(Vmar != ZX_HANDLE_INVALID && Vmar != _zx_vmar_root_self());
94 const zx_status_t Status =
95 _zx_vmar_unmap(Vmar, reinterpret_cast<zx_vaddr_t>(Ptr), Size);
96 Check(Status == ZX_OK, "Vmar unmapping failed");
97 }
98
getPlatformPageSize()99 size_t GuardedPoolAllocator::getPlatformPageSize() {
100 return _zx_system_get_page_size();
101 }
102
installAtFork()103 void GuardedPoolAllocator::installAtFork() {}
104 } // namespace gwp_asan
105