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 | Check(Status == ZX_OK, "Failed to create Vmo" ); |
28 | _zx_object_set_property(Vmo, ZX_PROP_NAME, Name, strlen(s: 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 | |
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 | Check(Status == ZX_OK, "Vmo unmapping failed" ); |
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 | Check(Status == ZX_OK, "Failed to reserve guarded pool allocator memory" ); |
54 | _zx_object_set_property(GuardedPagePoolPlatformData.Vmar, ZX_PROP_NAME, |
55 | kGwpAsanGuardPageName, strlen(s: kGwpAsanGuardPageName)); |
56 | return reinterpret_cast<void *>(Addr); |
57 | } |
58 | |
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 | |
67 | 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(s: 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 | |
88 | 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 | |
99 | size_t GuardedPoolAllocator::getPlatformPageSize() { |
100 | return _zx_system_get_page_size(); |
101 | } |
102 | |
103 | void GuardedPoolAllocator::installAtFork() {} |
104 | } // namespace gwp_asan |
105 | |