xref: /llvm-project/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_fuchsia.cpp (revision 0a94511aec7a41194c0e61d88801312542ff70ce)
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