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