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 : // A class that take care of initializing asan run-time library.
16 :
17 : #ifndef SYZYGY_AGENT_ASAN_RUNTIME_H_
18 : #define SYZYGY_AGENT_ASAN_RUNTIME_H_
19 :
20 : #include <memory>
21 : #include <set>
22 : #include <string>
23 :
24 : #include "base/callback.h"
25 : #include "base/logging.h"
26 : #include "base/synchronization/lock.h"
27 : #include "syzygy/agent/asan/error_info.h"
28 : #include "syzygy/agent/asan/heap_checker.h"
29 : #include "syzygy/agent/asan/memory_notifier.h"
30 : #include "syzygy/agent/asan/reporter.h"
31 : #include "syzygy/agent/asan/heap_managers/block_heap_manager.h"
32 : #include "syzygy/agent/common/stack_capture.h"
33 : #include "syzygy/common/asan_parameters.h"
34 :
35 : namespace agent {
36 : namespace asan {
37 :
38 : // Forward declarations.
39 : class AsanLogger;
40 :
41 : // An Asan Runtime manager.
42 : // This class takes care of initializing the different modules (stack cache,
43 : // logger...) and provide the functions to report an error.
44 : // Basic usage:
45 : // AsanRuntime* asan_runtime = new AsanRuntime();
46 : // std::wstring asan_flags_str;
47 : // AsanRuntime::GetAsanFlagsEnvVar(&asan_flags_str);
48 : // asan_runtime->SetUp(asan_flags_str); // Initialize the modules.
49 : // ...
50 : // AsanErrorInfo bad_access_info = {};
51 : // ::RtlCaptureContext(&bad_access_info.context);
52 : // StackCapture stack;
53 : // stack.InitFromStack();
54 : // stack.set_stack_id(stack.ComputeRelativeStackId());
55 : // bad_access_info.crash_stack_id = stack.stack_id();
56 : // asan_runtime->OnError(&bad_access_info);
57 : // asan_runtime->TearDown(); // Release the modules.
58 : // delete asan_runtime;
59 : class AsanRuntime {
60 : public:
61 : typedef std::set<common::StackCapture::StackId> StackIdSet;
62 :
63 : // The type of callback used by the OnError function.
64 : typedef base::Callback<void(AsanErrorInfo*)> AsanOnErrorCallBack;
65 :
66 : AsanRuntime();
67 : ~AsanRuntime();
68 :
69 : // @name Accessors.
70 : // @{
71 E : MemoryNotifierInterface* memory_notifier() const {
72 E : return memory_notifier_.get();
73 E : }
74 E : AsanLogger* logger() const { return logger_.get(); }
75 E : Shadow* shadow() const { return shadow_.get(); }
76 E : StackCaptureCache* stack_cache() const { return stack_cache_.get(); }
77 E : ReporterInterface* crash_reporter() const { return crash_reporter_.get(); }
78 : // @}
79 :
80 : // Initialize asan runtime library.
81 : // @param flags_command_line The parameters string.
82 : // @returns true on success, false otherwise.
83 : bool SetUp(const std::wstring& flags_command_line);
84 :
85 : // Release asan runtime library.
86 : void TearDown();
87 :
88 : // The body of the OnError functions, minus the error handler callback.
89 : // Factored out for reuse by OnError and unfiltered exception handling.
90 : // @param error_info The information about this error.
91 : void OnErrorImpl(AsanErrorInfo* error_info);
92 :
93 : // The error handler.
94 : // @param error_info The information about this error.
95 : void OnError(AsanErrorInfo* error_info);
96 :
97 : // Set the callback called on error.
98 : // TODO(sebmarchand): Move the signature of this callback to an header file
99 : // so it'll be easier to update it.
100 : void SetErrorCallBack(const AsanOnErrorCallBack& callback);
101 :
102 : // Try to read the Asan environment variable.
103 : // @param env_var_wstr The wstring where to store the environment variable.
104 : // returns true on success, false otherwise.
105 : static bool GetAsanFlagsEnvVar(std::wstring* env_var_wstr);
106 :
107 : // Returns true if we should ignore the given @p stack_id, false
108 : // otherwise.
109 E : bool ShouldIgnoreError(::common::AsanStackId stack_id) const {
110 : // TODO(sebmarchand): Keep a list of the stack ids that have already been
111 : // reported so we can avoid reporting the same error multiple times.
112 E : return params_.ignored_stack_ids_set.find(stack_id) !=
113 : params_.ignored_stack_ids_set.end();
114 E : }
115 :
116 : // Get information about a bad access.
117 : // @param bad_access_info Will receive the information about this access.
118 : void GetBadAccessInformation(AsanErrorInfo* error_info);
119 :
120 : // TODO(chrisha): Make this a proper singleton.
121 : // @returns the singleton runtime.
122 E : static AsanRuntime* runtime() { return runtime_; }
123 :
124 : // Accessors for runtime parameters.
125 E : ::common::InflatedAsanParameters& params() { return params_; }
126 : const ::common::InflatedAsanParameters& params() const { return params_; }
127 :
128 : // @returns the value of the tick counter when the runtime was created.
129 E : uint32_t starting_ticks() const { return starting_ticks_; }
130 :
131 : // Retrieves the process's heap.
132 : // @returns The ID of the process's heap.
133 E : HeapManagerInterface::HeapId GetProcessHeap() {
134 E : return heap_manager_->process_heap();
135 E : }
136 :
137 : // Returns the allocation-filter flag value.
138 : // @returns the allocation-filter flag value.
139 : // @note The flag is stored per-thread using TLS. Multiple threads do not
140 : // share the same flag.
141 : bool allocation_filter_flag();
142 :
143 : // Sets the allocation-filter flag to the specified value.
144 : // @param value the new value for the flag.
145 : // @note The flag is stored per-thread using TLS. Multiple threads do not
146 : // share the same flag.
147 : void set_allocation_filter_flag(bool value);
148 :
149 : // @names Accessors.
150 : // {
151 E : uint64_t random_key() const { return random_key_; }
152 : // @}
153 :
154 : // Observes a given thread ID, adding it to thread ID set.
155 : // @param thread_id The thread ID that has been observed.
156 : void AddThreadId(uint32_t thread_id);
157 :
158 : // Determines if a thread ID has already been seen.
159 : // @param thread_id The thread ID to be queried.
160 : // @returns true if a given thread ID is valid for this process.
161 : bool ThreadIdIsValid(uint32_t thread_id);
162 :
163 : // @name Introspection entry points into the block heap manager. These
164 : // are only meant to be run when the block heap manager lock is already
165 : // held, like during crash processing. If used in unittests care must be
166 : // taken to ensure the access is synchronous if the lock isn't otherwise
167 : // held.
168 : // @{
169 : // Determines if a given heap ID is valid.
170 : // @param uint32_t heap_id The heap ID to check.
171 : // @returns true if valid, false otherwise.
172 : bool HeapIdIsValid(HeapManagerInterface::HeapId heap_id);
173 :
174 : // Returns the type of a given heap.
175 : // @param uint32_t heap_id The heap ID to check.
176 : // @returns the heap type, or kUnknownHeapType if the heap is invalid.
177 : HeapType GetHeapType(HeapManagerInterface::HeapId heap_id);
178 : // @}
179 :
180 : // Processes an exception and determines if an Asan error has occurred,
181 : // updating the exception if so. If Breakpad is enabled, passes the
182 : // exception to it, otherwise lets the exception continue unhandled.
183 : // @note This is basically a Windows SEH exception filter.
184 : // @param exception The exception to be processed.
185 : // @returns EXCEPTION_CONTINUE_SEARCH or EXCEPTION_EXECUTE_HANDLER.
186 : static int CrashForException(EXCEPTION_POINTERS* exception);
187 :
188 : // Enables the deferred free thread.
189 : void EnableDeferredFreeThread();
190 :
191 : // Disables the deferred free thread.
192 : void DisableDeferredFreeThread();
193 :
194 : // @returns the list of enabled features.
195 : AsanFeatureSet GetEnabledFeatureSet();
196 :
197 : protected:
198 : // Propagate the values of the flags to the target modules.
199 : void PropagateParams();
200 :
201 : // @returns the space required to write the provided corrupt heap info.
202 : // @param corrupt_ranges The corrupt range info.
203 : size_t CalculateCorruptHeapInfoSize(
204 : const HeapChecker::CorruptRangesVector& corrupt_ranges);
205 :
206 : // Writes corrupt heap information to the provided buffer. This will write
207 : // as much of the information as possible in the space provided.
208 : // @param corrupt_ranges The corrupt range info.
209 : // @param buffer_size The size of the buffer to be written to. May be zero.
210 : // @param buffer The location where data will be written. May be null.
211 : // @param error_info The written heap metadata will be wired up to the
212 : // provided error_info.
213 : void WriteCorruptHeapInfo(
214 : const HeapChecker::CorruptRangesVector& corrupt_ranges,
215 : size_t buffer_size,
216 : void* buffer,
217 : AsanErrorInfo* error_info);
218 :
219 : // Logs information about an Asan error.
220 : void LogAsanErrorInfo(AsanErrorInfo* error_info);
221 :
222 : // @returns a value describing the state of the features that can be randomly
223 : // enabled or disabled.
224 : static AsanFeatureSet GenerateRandomFeatureSet();
225 :
226 : // Randomly enable some features.
227 : // @param feature_set The feature set indicating the features to update.
228 : void PropagateFeatureSet(AsanFeatureSet feature_set);
229 :
230 : // The heap manager.
231 : std::unique_ptr<heap_managers::BlockHeapManager>
232 : heap_manager_; // Under lock_.
233 :
234 : private:
235 : // Sets up the shadow memory.
236 : // @returns true on success, false otherwise.
237 : bool SetUpShadow();
238 :
239 : // Tears down the shadow memory.
240 : void TearDownShadow();
241 :
242 : // Set up the memory notifier.
243 : // @returns true on success, false otherwise.
244 : bool SetUpMemoryNotifier();
245 :
246 : // Tear down the memory notifier.
247 : void TearDownMemoryNotifier();
248 :
249 : // Set up the logger.
250 : // @returns true on success, false otherwise.
251 : bool SetUpLogger();
252 :
253 : // Tear down the logger.
254 : void TearDownLogger();
255 :
256 : // Set up the stack cache.
257 : // @returns true on success, false otherwise.
258 : bool SetUpStackCache();
259 :
260 : // Tear down the stack cache.
261 : void TearDownStackCache();
262 :
263 : // Set up the heap manager.
264 : // @returns true on success, false otherwise.
265 : bool SetUpHeapManager();
266 :
267 : // Tear down the heap manager.
268 : void TearDownHeapManager();
269 :
270 : // The unhandled exception filter registered by this runtime. This is used
271 : // to catch unhandled exceptions so we can augment them with information
272 : // about the corrupt heap.
273 : static LONG WINAPI UnhandledExceptionFilter(
274 : struct _EXCEPTION_POINTERS* exception);
275 :
276 : // The implementation of the Asan exception handler. This has two flavours:
277 : // in the context of an unhandled exception filter, and in the context of
278 : // an exception handler. If |is_unhandled| is true then this will pass the
279 : // exception along to the next unfiltered exception handler. Otherwise, it'll
280 : // pass it along to Breakpad, if present. Finally, it'll let the exception
281 : // processing continue unhandled.
282 : static LONG ExceptionFilterImpl(bool is_unhandled,
283 : EXCEPTION_POINTERS* exception);
284 :
285 : // @name Static variables related to unhandled exception filtering (UEF).
286 : // @{
287 : static base::Lock lock_; // Lock for all runtimes.
288 : static AsanRuntime* runtime_; // Singleton. Under lock_.
289 : static LPTOP_LEVEL_EXCEPTION_FILTER previous_uef_; // Under lock_.
290 : static bool uef_installed_; // Under lock_.
291 : // @}
292 :
293 : // The shadow memory used by this runtime.
294 : std::unique_ptr<Shadow> shadow_;
295 :
296 : // The shared memory notifier that will be used to update the shadow memory
297 : // with redzones for internally allocated memory.
298 : std::unique_ptr<MemoryNotifierInterface> memory_notifier_;
299 :
300 : // The shared logger instance that will be used to report errors and runtime
301 : // information.
302 : std::unique_ptr<AsanLogger> logger_;
303 :
304 : // The shared stack cache instance that will be used by all the heaps.
305 : std::unique_ptr<StackCaptureCache> stack_cache_;
306 :
307 : // The asan error callback functor.
308 : AsanOnErrorCallBack asan_error_callback_;
309 :
310 : // The runtime parameters.
311 : ::common::InflatedAsanParameters params_;
312 :
313 : // The tick counter when the runtime was created. This is used for
314 : // bracketing valid alloc and free ticks values.
315 : uint32_t starting_ticks_;
316 :
317 : // The set of thread IDs that have been seen in the current process.
318 : // This is used to validate thread IDs in a block trailer.
319 : base::Lock thread_ids_lock_;
320 : base::hash_set<uint32_t> thread_ids_; // Under thread_ids_lock_.
321 :
322 : // A random key that is generated on object creation. This is used for
323 : // correlating duplicate crash reports on the back-end.
324 : const uint64_t random_key_;
325 :
326 : // The crash reporter in use. This will be left null if no crash reporter
327 : // is available.
328 : std::unique_ptr<ReporterInterface> crash_reporter_;
329 :
330 : DISALLOW_COPY_AND_ASSIGN(AsanRuntime);
331 : };
332 :
333 : } // namespace asan
334 : } // namespace agent
335 :
336 : #endif // SYZYGY_AGENT_ASAN_RUNTIME_H_
|