1/*
2 * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include <wtf/Gigacage.h>
28
29#include <wtf/Atomics.h>
30#include <wtf/PageBlock.h>
31#include <wtf/OSAllocator.h>
32
33#if defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC
34
35namespace Gigacage {
36
37void* tryMalloc(Kind, size_t size)
38{
39 return FastMalloc::tryMalloc(size);
40}
41
42void* tryRealloc(Kind, void* pointer, size_t size)
43{
44 return FastMalloc::tryRealloc(pointer, size);
45}
46
47void* tryAllocateZeroedVirtualPages(Kind, size_t requestedSize)
48{
49 size_t size = roundUpToMultipleOf(WTF::pageSize(), requestedSize);
50 RELEASE_ASSERT(size >= requestedSize);
51 void* result = OSAllocator::reserveAndCommit(size);
52#if !ASSERT_DISABLED
53 if (result) {
54 for (size_t i = 0; i < size / sizeof(uintptr_t); ++i)
55 ASSERT(static_cast<uintptr_t*>(result)[i] == 0);
56 }
57#endif
58 return result;
59}
60
61void freeVirtualPages(Kind, void* basePtr, size_t size)
62{
63 OSAllocator::decommitAndRelease(basePtr, size);
64}
65
66} // namespace Gigacage
67#else // defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC
68#include <bmalloc/bmalloc.h>
69
70namespace Gigacage {
71
72// FIXME: Pointers into the primitive gigacage must be scrambled right after being returned from malloc,
73// and stay scrambled except just before use.
74// https://bugs.webkit.org/show_bug.cgi?id=175035
75
76void* tryAlignedMalloc(Kind kind, size_t alignment, size_t size)
77{
78 void* result = bmalloc::api::tryMemalign(alignment, size, bmalloc::heapKind(kind));
79 WTF::compilerFence();
80 return result;
81}
82
83void alignedFree(Kind kind, void* p)
84{
85 if (!p)
86 return;
87 RELEASE_ASSERT(isCaged(kind, p));
88 bmalloc::api::free(p, bmalloc::heapKind(kind));
89 WTF::compilerFence();
90}
91
92void* tryMalloc(Kind kind, size_t size)
93{
94 void* result = bmalloc::api::tryMalloc(size, bmalloc::heapKind(kind));
95 WTF::compilerFence();
96 return result;
97}
98
99void* tryRealloc(Kind kind, void* pointer, size_t size)
100{
101 void* result = bmalloc::api::tryRealloc(pointer, size, bmalloc::heapKind(kind));
102 WTF::compilerFence();
103 return result;
104}
105
106void free(Kind kind, void* p)
107{
108 if (!p)
109 return;
110 RELEASE_ASSERT(isCaged(kind, p));
111 bmalloc::api::free(p, bmalloc::heapKind(kind));
112 WTF::compilerFence();
113}
114
115void* tryAllocateZeroedVirtualPages(Kind kind, size_t size)
116{
117 void* result = bmalloc::api::tryLargeZeroedMemalignVirtual(WTF::pageSize(), size, bmalloc::heapKind(kind));
118 WTF::compilerFence();
119 return result;
120}
121
122void freeVirtualPages(Kind kind, void* basePtr, size_t size)
123{
124 if (!basePtr)
125 return;
126 RELEASE_ASSERT(isCaged(kind, basePtr));
127 bmalloc::api::freeLargeVirtual(basePtr, size, bmalloc::heapKind(kind));
128 WTF::compilerFence();
129}
130
131} // namespace Gigacage
132#endif
133
134namespace Gigacage {
135
136void* tryMallocArray(Kind kind, size_t numElements, size_t elementSize)
137{
138 Checked<size_t, RecordOverflow> checkedSize = elementSize;
139 checkedSize *= numElements;
140 if (checkedSize.hasOverflowed())
141 return nullptr;
142 return tryMalloc(kind, checkedSize.unsafeGet());
143}
144
145void* malloc(Kind kind, size_t size)
146{
147 void* result = tryMalloc(kind, size);
148 RELEASE_ASSERT(result);
149 return result;
150}
151
152void* mallocArray(Kind kind, size_t numElements, size_t elementSize)
153{
154 void* result = tryMallocArray(kind, numElements, elementSize);
155 RELEASE_ASSERT(result);
156 return result;
157}
158
159} // namespace Gigacage
160
161