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