1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/agent/asan/rtl_impl.h"
16 :
17 : #include <memory>
18 :
19 : #include "base/bind.h"
20 : #include "base/callback.h"
21 : #include "base/logging.h"
22 : #include "base/debug/alias.h"
23 : #include "syzygy/agent/asan/block.h"
24 : #include "syzygy/agent/asan/heap_manager.h"
25 : #include "syzygy/agent/asan/rtl_utils.h"
26 : #include "syzygy/agent/asan/runtime.h"
27 : #include "syzygy/agent/asan/shadow.h"
28 : #include "syzygy/agent/asan/windows_heap_adapter.h"
29 : #include "syzygy/agent/asan/heap_managers/block_heap_manager.h"
30 : #include "syzygy/agent/common/scoped_last_error_keeper.h"
31 : #include "syzygy/agent/common/stack_capture.h"
32 :
33 : namespace {
34 :
35 : using agent::asan::AsanErrorInfo;
36 : using agent::asan::AsanRuntime;
37 : using agent::asan::HeapManagerInterface;
38 : using agent::asan::Shadow;
39 : using agent::asan::WindowsHeapAdapter;
40 : using agent::asan::heap_managers::BlockHeapManager;
41 :
42 : HANDLE process_heap = NULL;
43 : HeapManagerInterface::HeapId asan_process_heap = NULL;
44 :
45 : // The asan runtime manager.
46 : AsanRuntime* asan_runtime = NULL;
47 :
48 : } // namespace
49 :
50 : namespace agent {
51 : namespace asan {
52 :
53 E : void SetUpRtl(AsanRuntime* runtime) {
54 E : DCHECK(runtime != NULL);
55 E : asan_runtime = runtime;
56 E : process_heap = ::GetProcessHeap();
57 :
58 : // Set the instance used by the helper functions.
59 E : SetAsanRuntimeInstance(runtime);
60 :
61 E : asan_process_heap = runtime->GetProcessHeap();
62 E : }
63 :
64 E : void TearDownRtl() {
65 E : DCHECK_NE(static_cast<HANDLE>(NULL), process_heap);
66 E : DCHECK_NE(static_cast<HeapManagerInterface::HeapId>(NULL), asan_process_heap);
67 E : process_heap = NULL;
68 E : asan_process_heap = NULL;
69 E : }
70 :
71 : } // namespace asan
72 : } // namespace agent
73 :
74 : extern "C" {
75 :
76 E : HANDLE WINAPI asan_GetProcessHeap() {
77 E : DCHECK_NE(static_cast<HANDLE>(NULL), process_heap);
78 E : DCHECK_NE(static_cast<HeapManagerInterface::HeapId>(NULL), asan_process_heap);
79 E : return reinterpret_cast<HANDLE>(asan_process_heap);
80 E : }
81 :
82 : HANDLE WINAPI asan_HeapCreate(DWORD options,
83 : SIZE_T initial_size,
84 E : SIZE_T maximum_size) {
85 E : return WindowsHeapAdapter::HeapCreate(options, initial_size, maximum_size);
86 E : }
87 :
88 E : BOOL WINAPI asan_HeapDestroy(HANDLE heap) {
89 E : DCHECK(process_heap != NULL);
90 E : if (heap == process_heap)
91 i : return ::HeapDestroy(heap);
92 :
93 E : return WindowsHeapAdapter::HeapDestroy(heap);
94 E : }
95 :
96 : LPVOID WINAPI asan_HeapAlloc(HANDLE heap,
97 : DWORD flags,
98 E : SIZE_T bytes) {
99 E : DCHECK(process_heap != NULL);
100 E : if (heap == process_heap)
101 i : return ::HeapAlloc(heap, flags, bytes);
102 :
103 E : return WindowsHeapAdapter::HeapAlloc(heap, flags, bytes);
104 E : }
105 :
106 : LPVOID WINAPI asan_HeapReAlloc(HANDLE heap,
107 : DWORD flags,
108 : LPVOID mem,
109 E : SIZE_T bytes) {
110 E : DCHECK(process_heap != NULL);
111 E : if (heap == process_heap)
112 i : return ::HeapReAlloc(heap, flags, mem, bytes);
113 :
114 E : return WindowsHeapAdapter::HeapReAlloc(heap, flags, mem, bytes);
115 E : }
116 :
117 : BOOL WINAPI asan_HeapFree(HANDLE heap,
118 : DWORD flags,
119 E : LPVOID mem) {
120 E : DCHECK(process_heap != NULL);
121 E : if (heap == process_heap)
122 i : return ::HeapFree(heap, flags, mem);
123 :
124 E : return WindowsHeapAdapter::HeapFree(heap, flags, mem);
125 E : }
126 :
127 : SIZE_T WINAPI asan_HeapSize(HANDLE heap,
128 : DWORD flags,
129 E : LPCVOID mem) {
130 E : DCHECK(process_heap != NULL);
131 E : if (heap == process_heap)
132 i : return ::HeapSize(heap, flags, mem);
133 :
134 E : return WindowsHeapAdapter::HeapSize(heap, flags, mem);
135 E : }
136 :
137 : BOOL WINAPI asan_HeapValidate(HANDLE heap,
138 : DWORD flags,
139 E : LPCVOID mem) {
140 E : DCHECK(process_heap != NULL);
141 E : if (heap == process_heap)
142 i : return ::HeapValidate(heap, flags, mem);
143 :
144 E : return WindowsHeapAdapter::HeapValidate(heap, flags, mem);
145 E : }
146 :
147 : SIZE_T WINAPI asan_HeapCompact(HANDLE heap,
148 E : DWORD flags) {
149 E : DCHECK(process_heap != NULL);
150 E : if (heap == process_heap)
151 i : return ::HeapCompact(heap, flags);
152 :
153 E : return WindowsHeapAdapter::HeapCompact(heap, flags);
154 E : }
155 :
156 E : BOOL WINAPI asan_HeapLock(HANDLE heap) {
157 E : DCHECK(process_heap != NULL);
158 E : if (heap == process_heap)
159 i : return ::HeapLock(heap);
160 :
161 E : return WindowsHeapAdapter::HeapLock(heap);
162 E : }
163 :
164 E : BOOL WINAPI asan_HeapUnlock(HANDLE heap) {
165 E : DCHECK(process_heap != NULL);
166 E : if (heap == process_heap)
167 i : return ::HeapUnlock(heap);
168 :
169 E : return WindowsHeapAdapter::HeapUnlock(heap);
170 E : }
171 :
172 : BOOL WINAPI asan_HeapWalk(HANDLE heap,
173 E : LPPROCESS_HEAP_ENTRY entry) {
174 E : DCHECK(process_heap != NULL);
175 E : if (heap == process_heap)
176 i : return ::HeapWalk(heap, entry);
177 :
178 E : return WindowsHeapAdapter::HeapWalk(heap, entry);
179 E : }
180 :
181 : BOOL WINAPI asan_HeapSetInformation(
182 : HANDLE heap, HEAP_INFORMATION_CLASS info_class,
183 E : PVOID info, SIZE_T info_length) {
184 E : DCHECK(process_heap != NULL);
185 E : if (heap == NULL || heap == process_heap)
186 E : return ::HeapSetInformation(heap, info_class, info, info_length);
187 :
188 E : return WindowsHeapAdapter::HeapSetInformation(heap, info_class, info,
189 : info_length);
190 E : }
191 :
192 : BOOL WINAPI asan_HeapQueryInformation(
193 : HANDLE heap, HEAP_INFORMATION_CLASS info_class,
194 E : PVOID info, SIZE_T info_length, PSIZE_T return_length) {
195 E : DCHECK(process_heap != NULL);
196 E : if (heap == NULL || heap == process_heap) {
197 i : return ::HeapQueryInformation(heap,
198 : info_class,
199 : info,
200 : info_length,
201 : return_length);
202 : }
203 :
204 E : return WindowsHeapAdapter::HeapQueryInformation(heap,
205 : info_class,
206 : info,
207 : info_length,
208 : return_length);
209 E : }
210 :
211 E : void WINAPI asan_SetCallBack(AsanErrorCallBack callback) {
212 E : DCHECK(asan_runtime != NULL);
213 E : asan_runtime->SetErrorCallBack(base::Bind(callback));
214 E : }
215 :
216 E : void WINAPI asan_SetOnExceptionCallback(OnExceptionCallback callback) {
217 E : if (callback != nullptr) {
218 E : agent::asan::SetOnExceptionCallback(base::Bind(callback));
219 E : } else {
220 i : agent::asan::ClearOnExceptionCallback();
221 : }
222 E : }
223 :
224 : #ifndef _WIN64
225 : // Unittesting seam.
226 E : AsanRuntime* WINAPI asan_GetActiveRuntime() {
227 E : return asan_runtime;
228 E : }
229 :
230 i : void __declspec(naked) asan_SetAllocationFilterFlag() {
231 : __asm {
232 i : pushad
233 i : pushfd
234 : }
235 i : asan_runtime->set_allocation_filter_flag(true);
236 : __asm {
237 i : popfd
238 i : popad
239 i : ret
240 : }
241 : }
242 :
243 i : void __declspec(naked) asan_ClearAllocationFilterFlag() {
244 : __asm {
245 i : pushad
246 i : pushfd
247 : }
248 i : asan_runtime->set_allocation_filter_flag(false);
249 : __asm {
250 i : popfd
251 i : popad
252 i : ret
253 : }
254 : }
255 : #endif // !defined _WIN64
256 :
257 i : int asan_CrashForException(EXCEPTION_POINTERS* exception) {
258 i : DCHECK_NE(static_cast<EXCEPTION_POINTERS*>(nullptr), exception);
259 i : return agent::asan::AsanRuntime::CrashForException(exception);
260 i : }
261 :
262 : } // extern "C"
|