1 : // Copyright 2013 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 : // Common unittest fixtures and utilities for the Asan runtime library.
16 :
17 : #include "syzygy/agent/asan/unittest_util.h"
18 :
19 : #include <algorithm>
20 :
21 : #include "base/bind.h"
22 : #include "base/command_line.h"
23 : #include "base/environment.h"
24 : #include "base/debug/alias.h"
25 : #include "base/process/kill.h"
26 : #include "base/process/launch.h"
27 : #include "base/strings/string_number_conversions.h"
28 : #include "base/strings/stringprintf.h"
29 : #include "base/strings/utf_string_conversions.h"
30 : #include "syzygy/agent/asan/asan_rtl_impl.h"
31 : #include "syzygy/agent/asan/asan_runtime.h"
32 : #include "syzygy/agent/asan/block.h"
33 : #include "syzygy/agent/asan/error_info.h"
34 : #include "syzygy/agent/asan/shadow.h"
35 : #include "syzygy/agent/common/stack_capture.h"
36 : #include "syzygy/trace/protocol/call_trace_defs.h"
37 :
38 : namespace testing {
39 :
40 : namespace {
41 :
42 : typedef agent::asan::HeapManagerInterface::HeapId HeapId;
43 :
44 : using agent::asan::BlockHeader;
45 : using agent::asan::BlockInfo;
46 : using agent::asan::BlockLayout;
47 : using agent::asan::Shadow;
48 : using agent::common::StackCapture;
49 :
50 : } // namespace
51 :
52 : const wchar_t kSyzyAsanRtlDll[] = L"syzyasan_rtl.dll";
53 : // The maximum time we're willing to wait for the logger process to get
54 : // started/killed. This is very generous, but also prevents the unittests
55 : // from hanging if the event never fires.
56 : static const size_t kLoggerTimeOutMs = 10000;
57 :
58 : namespace {
59 :
60 : FARPROC check_access_fn = NULL;
61 : bool direction_flag_forward = true;
62 :
63 : // An exception filter that grabs and sets an exception pointer, and
64 : // triggers only for access violations.
65 E : DWORD AccessViolationFilter(EXCEPTION_POINTERS* e, EXCEPTION_POINTERS** pe) {
66 E : if (e->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
67 E : *pe = e;
68 E : return EXCEPTION_EXECUTE_HANDLER;
69 : }
70 i : return EXCEPTION_CONTINUE_SEARCH;
71 E : }
72 :
73 : // Tries to access the given address, validating whether or not an
74 : // access violation occurs.
75 i : bool TestReadAccess(void* address, bool expect_access_violation) {
76 i : uint8* m = reinterpret_cast<uint8*>(address);
77 i : ULONG_PTR p = reinterpret_cast<ULONG_PTR>(address);
78 :
79 : // Try a read.
80 i : uint8 value = 0;
81 i : EXCEPTION_POINTERS* e = NULL;
82 i : __try {
83 i : value = m[0];
84 i : if (expect_access_violation)
85 i : return false;
86 i : }
87 i : __except(AccessViolationFilter(GetExceptionInformation(), &e)) {
88 i : if (!expect_access_violation)
89 i : return false;
90 : if (e->ExceptionRecord == NULL ||
91 : e->ExceptionRecord->NumberParameters < 2 ||
92 i : e->ExceptionRecord->ExceptionInformation[1] != p) {
93 i : return false;
94 : }
95 i : return true;
96 i : }
97 :
98 : // Ensure that |value| doesn't get optimized away. If so, the attempted
99 : // read never occurs.
100 i : base::debug::Alias(&value);
101 :
102 i : return true;
103 i : }
104 :
105 : // Tries to write at the given address, validating whether or not an
106 : // access violation occurs.
107 i : bool TestWriteAccess(void* address, bool expect_access_violation) {
108 i : uint8* m = reinterpret_cast<uint8*>(address);
109 i : ULONG_PTR p = reinterpret_cast<ULONG_PTR>(address);
110 :
111 : // Try a write.
112 i : EXCEPTION_POINTERS* e = NULL;
113 i : __try {
114 i : m[0] = 0;
115 i : if (expect_access_violation)
116 i : return false;
117 i : }
118 i : __except(AccessViolationFilter(GetExceptionInformation(), &e)) {
119 i : if (!expect_access_violation)
120 i : return false;
121 : if (e->ExceptionRecord == NULL ||
122 : e->ExceptionRecord->NumberParameters < 2 ||
123 i : e->ExceptionRecord->ExceptionInformation[1] != p) {
124 i : return false;
125 : }
126 i : }
127 :
128 i : return true;
129 i : }
130 :
131 : // Tries to access (read/write) at the given address, validating whether or
132 : // not an access violation occurs.
133 E : bool TestAccess(void* address, bool expect_access_violation) {
134 : return TestReadAccess(address, expect_access_violation) &&
135 E : TestWriteAccess(address, expect_access_violation);
136 E : }
137 :
138 : } // namespace
139 :
140 : MemoryAccessorTester* MemoryAccessorTester::instance_ = NULL;
141 :
142 : // Define the function pointers.
143 : #define DEFINE_FUNCTION_PTR_VARIABLE(convention, ret, name, args, argnames) \
144 : name##FunctionPtr TestAsanRtl::name##Function;
145 : ASAN_RTL_FUNCTIONS(DEFINE_FUNCTION_PTR_VARIABLE)
146 : #undef DEFINE_FUNCTION_PTR_VARIABLE
147 :
148 : // Define versions of all of the functions that expect an error to be thrown by
149 : // the AsanErrorCallback, and in turn raise an exception if the underlying
150 : // function didn't fail.
151 : #define DEFINE_FAILING_FUNCTION(convention, ret, name, args, argnames) \
152 : bool name##FunctionFailed args { \
153 : __try { \
154 : testing::TestAsanRtl::name##Function argnames; \
155 : } __except(::GetExceptionCode() == EXCEPTION_ARRAY_BOUNDS_EXCEEDED) { \
156 : return true; \
157 : } \
158 : return false; \
159 : } \
160 : void testing::TestAsanRtl::name##FunctionFailing args { \
161 : ASSERT_TRUE(name##FunctionFailed argnames); \
162 : }
163 E : ASAN_RTL_FUNCTIONS(DEFINE_FAILING_FUNCTION)
164 : #undef DEFINE_FAILING_FUNCTION
165 :
166 : TestWithAsanLogger::TestWithAsanLogger()
167 E : : logger_running_(false), log_contents_read_(false) {
168 E : }
169 :
170 E : void TestWithAsanLogger::SetUp() {
171 : // Create the log file.
172 E : ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
173 E : CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &log_file_path_));
174 :
175 : // Open files used to redirect standard in/out/err of the logger, to not
176 : // pollute the console.
177 : logger_stdin_file_.reset(base::OpenFile(
178 E : temp_dir_.path().AppendASCII("agent_logger_stdin.txt"), "w"));
179 E : CHECK(logger_stdin_file_);
180 : logger_stdout_file_.reset(base::OpenFile(
181 E : temp_dir_.path().AppendASCII("agent_logger_stdout.txt"), "w"));
182 E : CHECK(logger_stdout_file_);
183 : logger_stderr_file_.reset(base::OpenFile(
184 E : temp_dir_.path().AppendASCII("agent_logger_stderr.txt"), "w"));
185 E : CHECK(logger_stderr_file_);
186 :
187 : // Save the environment we found.
188 E : scoped_ptr<base::Environment> env(base::Environment::Create());
189 E : env->GetVar(kSyzygyRpcInstanceIdEnvVar, &old_logger_env_);
190 :
191 : // Configure the environment (to pass the instance id to the agent DLL).
192 : // We append "-0" to the process id to avoid potential conflict with other
193 : // tests.
194 E : instance_id_ = base::UintToString16(::GetCurrentProcessId()) + L"-0";
195 : AppendToLoggerEnv(base::StringPrintf("%ls,%ls",
196 : kSyzyAsanRtlDll,
197 E : instance_id_.c_str()));
198 :
199 E : log_contents_read_ = false;
200 E : StartLogger();
201 E : }
202 :
203 E : void TestWithAsanLogger::TearDown() {
204 E : StopLogger();
205 :
206 : // Restore the environment variable as we found it.
207 E : scoped_ptr<base::Environment> env(base::Environment::Create());
208 E : env->SetVar(kSyzygyRpcInstanceIdEnvVar, old_logger_env_);
209 E : }
210 :
211 E : bool TestWithAsanLogger::LogContains(const base::StringPiece& message) {
212 E : if (!log_contents_read_ && logger_running_) {
213 E : CHECK(base::ReadFileToString(log_file_path_, &log_contents_));
214 E : log_contents_read_ = true;
215 : }
216 E : return log_contents_.find(message.as_string()) != std::string::npos;
217 E : }
218 :
219 E : void TestWithAsanLogger::DeleteTempFileAndDirectory() {
220 E : StopLogger();
221 E : logger_stdin_file_.reset();
222 E : logger_stdout_file_.reset();
223 E : logger_stderr_file_.reset();
224 E : if (temp_dir_.IsValid())
225 E : temp_dir_.Delete();
226 E : }
227 :
228 E : void TestWithAsanLogger::StartLogger() {
229 : // Launch the logger as a separate process and make sure it succeeds.
230 E : base::CommandLine cmd_line(testing::GetExeRelativePath(L"agent_logger.exe"));
231 E : cmd_line.AppendSwitchNative("instance-id", instance_id_);
232 E : cmd_line.AppendSwitchNative("output-file", log_file_path_.value());
233 E : cmd_line.AppendSwitchNative("minidump-dir", temp_dir_.path().value());
234 E : cmd_line.AppendArgNative(L"start");
235 E : base::LaunchOptions options;
236 E : options.start_hidden = true;
237 : options.stdin_handle = reinterpret_cast<HANDLE>(
238 E : _get_osfhandle(_fileno(logger_stdin_file_.get())));
239 : options.stdout_handle = reinterpret_cast<HANDLE>(
240 E : _get_osfhandle(_fileno(logger_stdout_file_.get())));
241 : options.stderr_handle = reinterpret_cast<HANDLE>(
242 E : _get_osfhandle(_fileno(logger_stderr_file_.get())));
243 E : options.inherit_handles = true; // As per documentation.
244 E : bool success = base::LaunchProcess(cmd_line, options, NULL);
245 E : ASSERT_TRUE(success);
246 :
247 : // Wait for the logger to be ready before continuing.
248 E : std::wstring event_name;
249 : trace::agent_logger::AgentLogger::GetSyzygyAgentLoggerEventName(
250 E : instance_id_, &event_name);
251 : base::win::ScopedHandle event(
252 E : ::CreateEvent(NULL, FALSE, FALSE, event_name.c_str()));
253 E : ::WaitForSingleObject(event.Get(), kLoggerTimeOutMs);
254 E : logger_running_ = true;
255 E : }
256 :
257 E : void TestWithAsanLogger::StopLogger() {
258 E : if (!logger_running_)
259 E : return;
260 : // Launch the logger as a separate process to stop it and make sure it
261 : // succeeds.
262 E : base::CommandLine cmd_line(base::FilePath(L"agent_logger.exe"));
263 E : cmd_line.AppendSwitchNative("instance-id", instance_id_);
264 E : cmd_line.AppendArgNative(L"stop");
265 E : base::LaunchOptions options;
266 E : options.start_hidden = true;
267 : base::ProcessHandle logger_process;
268 E : bool success = base::LaunchProcess(cmd_line, options, &logger_process);
269 E : ASSERT_TRUE(success);
270 : ASSERT_TRUE(base::WaitForSingleProcess(logger_process,
271 E : base::TimeDelta::FromMilliseconds(kLoggerTimeOutMs)));
272 E : logger_running_ = false;
273 E : }
274 :
275 E : void TestWithAsanLogger::ResetLog() {
276 E : StopLogger();
277 E : CHECK(base::CreateTemporaryFileInDir(temp_dir_.path(), &log_file_path_));
278 E : StartLogger();
279 E : log_contents_read_ = false;
280 E : }
281 :
282 E : void TestWithAsanLogger::AppendToLoggerEnv(const std::string &instance) {
283 E : std::string instance_id;
284 E : scoped_ptr<base::Environment> env(base::Environment::Create());
285 E : env->GetVar(kSyzygyRpcInstanceIdEnvVar, &instance_id);
286 :
287 E : instance_id.append(";");
288 E : instance_id.append(instance);
289 :
290 E : env->SetVar(kSyzygyRpcInstanceIdEnvVar, instance_id);
291 E : }
292 :
293 : FakeAsanBlock::FakeAsanBlock(size_t alloc_alignment_log,
294 : StackCaptureCache* stack_cache)
295 : : is_initialized(false), alloc_alignment_log(alloc_alignment_log),
296 E : alloc_alignment(1 << alloc_alignment_log), stack_cache(stack_cache) {
297 : // Align the beginning of the buffer to the current granularity. Ensure that
298 : // there's room to store magic bytes in front of this block.
299 : buffer_align_begin = reinterpret_cast<uint8*>(common::AlignUp(
300 E : reinterpret_cast<size_t>(buffer)+1, alloc_alignment));
301 E : ::memset(&block_info, 0, sizeof(block_info));
302 E : }
303 :
304 E : FakeAsanBlock::~FakeAsanBlock() {
305 E : EXPECT_NE(0U, block_info.block_size);
306 E : Shadow::Unpoison(buffer_align_begin, block_info.block_size);
307 E : ::memset(buffer, 0, sizeof(buffer));
308 E : }
309 :
310 E : bool FakeAsanBlock::InitializeBlock(size_t alloc_size) {
311 E : BlockLayout layout = {};
312 : EXPECT_TRUE(BlockPlanLayout(alloc_alignment,
313 : alloc_alignment,
314 : alloc_size,
315 : 0,
316 : 0,
317 E : &layout));
318 :
319 : // Initialize the Asan block.
320 E : BlockInitialize(layout, buffer_align_begin, false, &block_info);
321 E : EXPECT_NE(reinterpret_cast<void*>(NULL), block_info.body);
322 :
323 E : StackCapture stack;
324 E : stack.InitFromStack();
325 E : block_info.header->alloc_stack = stack_cache->SaveStackTrace(stack);
326 :
327 E : Shadow::PoisonAllocatedBlock(block_info);
328 E : BlockSetChecksum(block_info);
329 :
330 : // Calculate the size of the zone of the buffer that we use to ensure that
331 : // we don't corrupt the heap.
332 E : buffer_header_size = buffer_align_begin - buffer;
333 : buffer_trailer_size = kBufferSize - buffer_header_size -
334 E : block_info.block_size;
335 E : EXPECT_GT(kBufferSize, layout.block_size + buffer_header_size);
336 :
337 : // Initialize the buffer header and trailer.
338 E : ::memset(buffer, kBufferHeaderValue, buffer_header_size);
339 : ::memset(buffer_align_begin + block_info.block_size, kBufferTrailerValue,
340 E : buffer_trailer_size);
341 :
342 : EXPECT_TRUE(common::IsAligned(reinterpret_cast<size_t>(block_info.body),
343 E : alloc_alignment));
344 : EXPECT_TRUE(common::IsAligned(
345 : reinterpret_cast<size_t>(buffer_align_begin) + block_info.block_size,
346 E : agent::asan::kShadowRatio));
347 E : EXPECT_EQ(buffer_align_begin, block_info.block);
348 :
349 : void* expected_user_ptr = reinterpret_cast<void*>(
350 E : buffer_align_begin + std::max(sizeof(BlockHeader), alloc_alignment));
351 E : EXPECT_EQ(block_info.body, expected_user_ptr);
352 :
353 E : size_t i = 0;
354 : // Ensure that the buffer header is accessible and correctly tagged.
355 E : for (; i < buffer_header_size; ++i) {
356 E : EXPECT_EQ(kBufferHeaderValue, buffer[i]);
357 E : EXPECT_TRUE(Shadow::IsAccessible(buffer + i));
358 E : }
359 E : size_t user_block_offset = block_info.body - buffer;
360 : // Ensure that the block header isn't accessible.
361 E : for (; i < user_block_offset; ++i)
362 E : EXPECT_FALSE(Shadow::IsAccessible(buffer + i));
363 :
364 : // Ensure that the user block is accessible.
365 E : size_t block_trailer_offset = i + alloc_size;
366 E : for (; i < block_trailer_offset; ++i)
367 E : EXPECT_TRUE(Shadow::IsAccessible(buffer + i));
368 :
369 : // Ensure that the block trailer isn't accessible.
370 E : for (; i < buffer_header_size + block_info.block_size; ++i)
371 E : EXPECT_FALSE(Shadow::IsAccessible(buffer + i));
372 :
373 : // Ensure that the buffer trailer is accessible and correctly tagged.
374 E : for (; i < kBufferSize; ++i) {
375 E : EXPECT_EQ(kBufferTrailerValue, buffer[i]);
376 E : EXPECT_TRUE(Shadow::IsAccessible(buffer + i));
377 E : }
378 :
379 E : is_initialized = true;
380 E : return true;
381 E : }
382 :
383 : bool FakeAsanBlock::TestBlockMetadata() {
384 : if (!is_initialized)
385 : return false;
386 :
387 : // Ensure that the block header is valid. BlockGetHeaderFromBody takes
388 : // care of checking the magic number in the signature of the block.
389 : BlockHeader* block_header = block_info.header;
390 : EXPECT_NE(static_cast<BlockHeader*>(NULL), block_header);
391 : BlockInfo block_info = {};
392 : EXPECT_TRUE(BlockInfoFromMemory(block_header, &block_info));
393 : const uint8* cursor = buffer_align_begin;
394 : EXPECT_EQ(::GetCurrentThreadId(), block_info.trailer->alloc_tid);
395 : EXPECT_TRUE(block_header->alloc_stack != NULL);
396 : EXPECT_EQ(agent::asan::ALLOCATED_BLOCK, block_header->state);
397 : EXPECT_TRUE(Shadow::IsBlockStartByte(cursor++));
398 : for (; cursor < block_info.body; ++cursor)
399 : EXPECT_TRUE(Shadow::IsLeftRedzone(cursor));
400 : const uint8* aligned_trailer_begin = reinterpret_cast<const uint8*>(
401 : common::AlignUp(reinterpret_cast<size_t>(block_info.body) +
402 : block_info.body_size,
403 : agent::asan::kShadowRatio));
404 : for (const uint8* pos = aligned_trailer_begin;
405 : pos < buffer_align_begin + block_info.block_size;
406 : ++pos) {
407 : EXPECT_TRUE(Shadow::IsRightRedzone(pos));
408 : }
409 :
410 : return true;
411 : }
412 :
413 E : bool FakeAsanBlock::MarkBlockAsQuarantined() {
414 E : if (!is_initialized)
415 i : return false;
416 :
417 E : EXPECT_NE(static_cast<BlockHeader*>(NULL), block_info.header);
418 E : EXPECT_TRUE(block_info.header->free_stack == NULL);
419 E : EXPECT_TRUE(block_info.trailer != NULL);
420 E : EXPECT_EQ(0U, block_info.trailer->free_tid);
421 :
422 E : Shadow::MarkAsFreed(block_info.body, block_info.body_size);
423 E : StackCapture stack;
424 E : stack.InitFromStack();
425 E : block_info.header->free_stack = stack_cache->SaveStackTrace(stack);
426 E : block_info.header->state = agent::asan::QUARANTINED_BLOCK;
427 E : block_info.trailer->free_tid = ::GetCurrentThreadId();
428 E : block_info.trailer->free_ticks = ::GetTickCount();
429 E : BlockSetChecksum(block_info);
430 :
431 E : size_t i = 0;
432 : // Ensure that the buffer header is accessible and correctly tagged.
433 E : for (; i < buffer_header_size; ++i) {
434 E : EXPECT_EQ(kBufferHeaderValue, buffer[i]);
435 E : EXPECT_TRUE(Shadow::IsAccessible(buffer + i));
436 E : }
437 : // Ensure that the whole block isn't accessible.
438 E : for (; i < buffer_header_size + block_info.block_size; ++i)
439 E : EXPECT_FALSE(Shadow::IsAccessible(buffer + i));
440 :
441 : // Ensure that the buffer trailer is accessible and correctly tagged.
442 E : for (; i < kBufferSize; ++i) {
443 E : EXPECT_EQ(kBufferTrailerValue, buffer[i]);
444 E : EXPECT_TRUE(Shadow::IsAccessible(buffer + i));
445 E : }
446 E : return true;
447 E : }
448 :
449 : namespace {
450 :
451 : #define RTL_CAPTURE_CONTEXT(context, expected_eip) { \
452 : /* Save caller save registers. */ \
453 : __asm push eax \
454 : __asm push ecx \
455 : __asm push edx \
456 : /* Call Capture context. */ \
457 : __asm push context \
458 : __asm call dword ptr[RtlCaptureContext] \
459 : /* Restore caller save registers. */ \
460 : __asm pop edx \
461 : __asm pop ecx \
462 : __asm pop eax \
463 : /* Restore registers which are stomped by RtlCaptureContext. */ \
464 : __asm push eax \
465 : __asm pushfd \
466 : __asm mov eax, context \
467 : __asm mov dword ptr[eax + CONTEXT.Ebp], ebp \
468 : __asm mov dword ptr[eax + CONTEXT.Esp], esp \
469 : /* NOTE: we need to add 8 bytes because EAX + EFLAGS are on the stack. */ \
470 : __asm add dword ptr[eax + CONTEXT.Esp], 8 \
471 : __asm mov dword ptr[eax + CONTEXT.Eip], offset expected_eip \
472 : __asm popfd \
473 : __asm pop eax \
474 : }
475 :
476 : // Check whether 2 contexts are equal.
477 : // @param c1 The first context to check.
478 : // @param c2 The second context to check.
479 : void ExpectEqualContexts(const CONTEXT& c1,
480 : const CONTEXT& c2,
481 E : bool ignore_flags) {
482 : // Segment registers.
483 E : EXPECT_EQ(static_cast<WORD>(c1.SegGs), static_cast<WORD>(c2.SegGs));
484 E : EXPECT_EQ(static_cast<WORD>(c1.SegFs), static_cast<WORD>(c2.SegFs));
485 E : EXPECT_EQ(static_cast<WORD>(c1.SegEs), static_cast<WORD>(c2.SegEs));
486 E : EXPECT_EQ(static_cast<WORD>(c1.SegDs), static_cast<WORD>(c2.SegDs));
487 :
488 : // General registers.
489 E : EXPECT_EQ(c1.Edi, c2.Edi);
490 E : EXPECT_EQ(c1.Esi, c2.Esi);
491 E : EXPECT_EQ(c1.Ebx, c2.Ebx);
492 E : EXPECT_EQ(c1.Edx, c2.Edx);
493 E : EXPECT_EQ(c1.Ecx, c2.Ecx);
494 E : EXPECT_EQ(c1.Eax, c2.Eax);
495 :
496 : // "Control" registers.
497 E : EXPECT_EQ(c1.Ebp, c2.Ebp);
498 E : EXPECT_EQ(c1.Eip, c2.Eip);
499 E : EXPECT_EQ(static_cast<WORD>(c1.SegCs), static_cast<WORD>(c2.SegCs));
500 E : if (!ignore_flags)
501 E : EXPECT_EQ(c1.EFlags, c2.EFlags);
502 E : EXPECT_EQ(c1.Esp, c2.Esp);
503 E : EXPECT_EQ(static_cast<WORD>(c1.SegSs), static_cast<WORD>(c2.SegSs));
504 E : }
505 :
506 : } // namespace
507 :
508 : MemoryAccessorTester::MemoryAccessorTester()
509 : : expected_error_type_(agent::asan::UNKNOWN_BAD_ACCESS),
510 : memory_error_detected_(false),
511 E : ignore_flags_(false) {
512 E : EXPECT_EQ(static_cast<MemoryAccessorTester*>(NULL), instance_);
513 :
514 E : Initialize();
515 E : instance_ = this;
516 E : }
517 :
518 : MemoryAccessorTester::MemoryAccessorTester(IgnoreFlags /* ignore_flags */)
519 : : expected_error_type_(agent::asan::UNKNOWN_BAD_ACCESS),
520 : memory_error_detected_(false),
521 E : ignore_flags_(true) {
522 E : EXPECT_EQ(static_cast<MemoryAccessorTester*>(NULL), instance_);
523 :
524 E : Initialize();
525 E : instance_ = this;
526 E : }
527 :
528 E : MemoryAccessorTester::~MemoryAccessorTester() {
529 E : EXPECT_EQ(this, instance_);
530 E : instance_ = NULL;
531 E : }
532 :
533 E : void MemoryAccessorTester::Initialize() {
534 E : ::memset(&context_before_hook_, 0xCD, sizeof(context_before_hook_));
535 E : ::memset(&context_after_hook_, 0xCE, sizeof(context_after_hook_));
536 E : ::memset(&error_context_, 0xCF, sizeof(error_context_));
537 E : ::memset(&last_error_info_, 0, sizeof(last_error_info_));
538 E : }
539 :
540 : namespace {
541 :
542 : void CheckAccessAndCaptureContexts(
543 i : CONTEXT* before, CONTEXT* after, void* location) {
544 : __asm {
545 i : pushad
546 i : pushfd
547 :
548 : // Avoid undefined behavior by forcing values.
549 i : mov eax, 0x01234567
550 i : mov ebx, 0x70123456
551 i : mov ecx, 0x12345678
552 i : mov edx, 0x56701234
553 i : mov esi, 0xCCAACCAA
554 i : mov edi, 0xAACCAACC
555 :
556 i : RTL_CAPTURE_CONTEXT(before, check_access_expected_eip)
557 :
558 : // Push EDX as we're required to do by the custom calling convention.
559 i : push edx
560 : // Ptr is the pointer to check.
561 i : mov edx, location
562 : // Call through.
563 i : call dword ptr[check_access_fn + 0]
564 : check_access_expected_eip:
565 :
566 i : RTL_CAPTURE_CONTEXT(after, check_access_expected_eip)
567 :
568 i : popfd
569 i : popad
570 : }
571 i : }
572 :
573 : } // namespace
574 :
575 : void MemoryAccessorTester::CheckAccessAndCompareContexts(
576 E : FARPROC access_fn, void* ptr) {
577 E : memory_error_detected_ = false;
578 :
579 E : check_access_fn = access_fn;
580 :
581 : CheckAccessAndCaptureContexts(
582 E : &context_before_hook_, &context_after_hook_, ptr);
583 :
584 : ExpectEqualContexts(context_before_hook_,
585 : context_after_hook_,
586 E : ignore_flags_);
587 E : if (memory_error_detected_) {
588 : ExpectEqualContexts(context_before_hook_,
589 : error_context_,
590 E : ignore_flags_);
591 : }
592 :
593 E : check_access_fn = NULL;
594 E : }
595 :
596 : namespace {
597 :
598 : void CheckSpecialAccess(CONTEXT* before, CONTEXT* after,
599 i : void* dst, void* src, int len) {
600 : __asm {
601 i : pushad
602 i : pushfd
603 :
604 : // Override the direction flag.
605 i : cld
606 i : cmp direction_flag_forward, 0
607 i : jne skip_reverse_direction
608 i : std
609 : skip_reverse_direction:
610 :
611 : // Avoid undefined behavior by forcing values.
612 i : mov eax, 0x01234567
613 i : mov ebx, 0x70123456
614 i : mov edx, 0x56701234
615 :
616 : // Setup registers used by the special instruction.
617 i : mov ecx, len
618 E : mov esi, src
619 i : mov edi, dst
620 :
621 i : RTL_CAPTURE_CONTEXT(before, special_access_expected_eip)
622 :
623 : // Call through.
624 i : call dword ptr[check_access_fn + 0]
625 : special_access_expected_eip:
626 :
627 i : RTL_CAPTURE_CONTEXT(after, special_access_expected_eip)
628 :
629 i : popfd
630 i : popad
631 : }
632 i : }
633 :
634 : } // namespace
635 :
636 : void MemoryAccessorTester::CheckSpecialAccessAndCompareContexts(
637 : FARPROC access_fn, StringOperationDirection direction,
638 E : void* dst, void* src, int len) {
639 E : memory_error_detected_ = false;
640 :
641 E : direction_flag_forward = (direction == DIRECTION_FORWARD);
642 E : check_access_fn = access_fn;
643 :
644 : CheckSpecialAccess(
645 E : &context_before_hook_, &context_after_hook_, dst, src, len);
646 :
647 : ExpectEqualContexts(context_before_hook_,
648 : context_after_hook_,
649 E : ignore_flags_);
650 E : if (memory_error_detected_) {
651 : ExpectEqualContexts(context_before_hook_,
652 : error_context_,
653 E : ignore_flags_);
654 : }
655 :
656 E : check_access_fn = NULL;
657 E : }
658 :
659 E : void MemoryAccessorTester::AsanErrorCallbackImpl(AsanErrorInfo* error_info) {
660 : // TODO(sebmarchand): Stash the error info in a fixture-static variable and
661 : // assert on specific conditions after the fact.
662 E : EXPECT_NE(reinterpret_cast<AsanErrorInfo*>(NULL), error_info);
663 E : EXPECT_NE(agent::asan::UNKNOWN_BAD_ACCESS, error_info->error_type);
664 :
665 E : EXPECT_EQ(expected_error_type_, error_info->error_type);
666 E : if (error_info->error_type >= agent::asan::USE_AFTER_FREE) {
667 : // We should at least have the stack trace of the allocation of this block.
668 E : EXPECT_GT(error_info->block_info.alloc_stack_size, 0U);
669 E : EXPECT_NE(0U, error_info->block_info.alloc_tid);
670 : if (error_info->error_type == agent::asan::USE_AFTER_FREE ||
671 E : error_info->error_type == agent::asan::DOUBLE_FREE) {
672 E : EXPECT_GT(error_info->block_info.free_stack_size, 0U);
673 E : EXPECT_NE(0U, error_info->block_info.free_tid);
674 E : } else {
675 E : EXPECT_EQ(error_info->block_info.free_stack_size, 0U);
676 E : EXPECT_EQ(0U, error_info->block_info.free_tid);
677 : }
678 : }
679 :
680 E : if (error_info->error_type == agent::asan::HEAP_BUFFER_OVERFLOW) {
681 E : EXPECT_TRUE(strstr(error_info->shadow_info, "beyond") != NULL);
682 E : } else if (error_info->error_type == agent::asan::HEAP_BUFFER_UNDERFLOW) {
683 E : EXPECT_TRUE(strstr(error_info->shadow_info, "before") != NULL);
684 : }
685 :
686 E : memory_error_detected_ = true;
687 E : last_error_info_ = *error_info;
688 :
689 : // Copy the corrupt range's information.
690 E : if (error_info->heap_is_corrupt) {
691 E : EXPECT_GE(1U, error_info->corrupt_range_count);
692 E : for (size_t i = 0; i < error_info->corrupt_range_count; ++i) {
693 E : last_corrupt_ranges_.push_back(CorruptRangeInfo());
694 E : CorruptRangeInfo* range_info = &last_corrupt_ranges_.back();
695 E : range_info->first = error_info->corrupt_ranges[i];
696 E : AsanBlockInfoVector* block_infos = &range_info->second;
697 E : for (size_t j = 0; j < range_info->first.block_info_count; ++j) {
698 E : agent::asan::AsanBlockInfo block_info = range_info->first.block_info[j];
699 E : for (size_t k = 0;
700 E : k < range_info->first.block_info[j].alloc_stack_size;
701 E : ++k) {
702 : block_info.alloc_stack[k] =
703 E : range_info->first.block_info[j].alloc_stack[k];
704 E : }
705 E : for (size_t k = 0;
706 E : k < range_info->first.block_info[j].free_stack_size;
707 E : ++k) {
708 : block_info.free_stack[k] =
709 i : range_info->first.block_info[j].free_stack[k];
710 i : }
711 E : block_infos->push_back(block_info);
712 E : }
713 E : }
714 : }
715 :
716 E : error_context_ = error_info->context;
717 E : }
718 :
719 E : void MemoryAccessorTester::AsanErrorCallback(AsanErrorInfo* error_info) {
720 E : ASSERT_NE(reinterpret_cast<MemoryAccessorTester*>(NULL), instance_);
721 :
722 E : instance_->AsanErrorCallbackImpl(error_info);
723 E : }
724 :
725 : void MemoryAccessorTester::AssertMemoryErrorIsDetected(
726 E : FARPROC access_fn, void* ptr, BadAccessKind bad_access_type) {
727 E : expected_error_type_ = bad_access_type;
728 E : CheckAccessAndCompareContexts(access_fn, ptr);
729 E : ASSERT_TRUE(memory_error_detected_);
730 E : }
731 :
732 : void MemoryAccessorTester::ExpectSpecialMemoryErrorIsDetected(
733 : FARPROC access_fn, StringOperationDirection direction,
734 : bool expect_error, void* dst, void* src, int32 length,
735 E : BadAccessKind bad_access_type) {
736 E : DCHECK(dst != NULL);
737 E : DCHECK(src != NULL);
738 E : ASSERT_TRUE(check_access_fn == NULL);
739 :
740 E : expected_error_type_ = bad_access_type;
741 :
742 : // Perform memory accesses inside the range.
743 : ASSERT_NO_FATAL_FAILURE(
744 : CheckSpecialAccessAndCompareContexts(
745 E : access_fn, direction, dst, src, length));
746 :
747 E : EXPECT_EQ(expect_error, memory_error_detected_);
748 E : check_access_fn = NULL;
749 E : }
750 :
751 : TestMemoryInterceptors::TestMemoryInterceptors()
752 E : : heap_(NULL), src_(NULL), dst_(NULL) {
753 E : }
754 :
755 E : void TestMemoryInterceptors::SetUp() {
756 E : testing::TestWithAsanLogger::SetUp();
757 :
758 : // Make sure the logging routes to our instance.
759 : AppendToLoggerEnv(base::StringPrintf("syzyasan_rtl_unittests.exe,%u",
760 E : ::GetCurrentProcessId()));
761 :
762 E : asan_runtime_.SetUp(std::wstring());
763 :
764 : // Heap checking on error is expensive, so turn it down here.
765 E : asan_runtime_.params().check_heap_on_failure = false;
766 :
767 E : agent::asan::SetUpRtl(&asan_runtime_);
768 :
769 : asan_runtime_.SetErrorCallBack(
770 E : base::Bind(testing::MemoryAccessorTester::AsanErrorCallback));
771 E : heap_ = asan_HeapCreate(0, 0, 0);
772 E : ASSERT_TRUE(heap_ != NULL);
773 :
774 E : src_ = reinterpret_cast<byte*>(asan_HeapAlloc(heap_, 0, kAllocSize));
775 E : dst_ = reinterpret_cast<byte*>(asan_HeapAlloc(heap_, 0, kAllocSize));
776 E : ASSERT_TRUE(src_ && dst_);
777 :
778 : // String instructions may compare memory contents and bail early on
779 : // differences, so fill the buffers to make sure the checks go the full
780 : // distance.
781 E : ::memset(src_, 0xFF, kAllocSize);
782 E : ::memset(dst_, 0xFF, kAllocSize);
783 E : }
784 :
785 E : void TestMemoryInterceptors::TearDown() {
786 E : if (heap_ != NULL) {
787 E : asan_HeapFree(heap_, 0, src_);
788 E : asan_HeapFree(heap_, 0, dst_);
789 :
790 E : asan_HeapDestroy(heap_);
791 E : heap_ = NULL;
792 : }
793 E : agent::asan::TearDownRtl();
794 E : asan_runtime_.TearDown();
795 E : testing::TestWithAsanLogger::TearDown();
796 E : }
797 :
798 : void TestMemoryInterceptors::TestValidAccess(
799 E : const InterceptFunction* fns, size_t num_fns) {
800 E : for (size_t i = 0; i < num_fns; ++i) {
801 E : const InterceptFunction& fn = fns[i];
802 :
803 E : MemoryAccessorTester tester;
804 : tester.CheckAccessAndCompareContexts(
805 E : reinterpret_cast<FARPROC>(fn.function), src_);
806 :
807 E : ASSERT_FALSE(tester.memory_error_detected());
808 E : }
809 E : }
810 :
811 : void TestMemoryInterceptors::TestValidAccessIgnoreFlags(
812 E : const InterceptFunction* fns, size_t num_fns) {
813 E : for (size_t i = 0; i < num_fns; ++i) {
814 E : const InterceptFunction& fn = fns[i];
815 :
816 E : MemoryAccessorTester tester(MemoryAccessorTester::IGNORE_FLAGS);
817 : tester.CheckAccessAndCompareContexts(
818 E : reinterpret_cast<FARPROC>(fn.function), src_);
819 :
820 E : ASSERT_FALSE(tester.memory_error_detected());
821 E : }
822 E : }
823 :
824 : void TestMemoryInterceptors::TestOverrunAccess(
825 E : const InterceptFunction* fns, size_t num_fns) {
826 E : for (size_t i = 0; i < num_fns; ++i) {
827 E : const InterceptFunction& fn = fns[i];
828 :
829 E : MemoryAccessorTester tester;
830 : tester.AssertMemoryErrorIsDetected(
831 : reinterpret_cast<FARPROC>(fn.function),
832 : src_ + kAllocSize,
833 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
834 :
835 E : ASSERT_TRUE(tester.memory_error_detected());
836 E : }
837 E : }
838 :
839 : void TestMemoryInterceptors::TestOverrunAccessIgnoreFlags(
840 E : const InterceptFunction* fns, size_t num_fns) {
841 E : for (size_t i = 0; i < num_fns; ++i) {
842 E : const InterceptFunction& fn = fns[i];
843 :
844 E : MemoryAccessorTester tester(MemoryAccessorTester::IGNORE_FLAGS);
845 : tester.AssertMemoryErrorIsDetected(
846 : reinterpret_cast<FARPROC>(fn.function),
847 : src_ + kAllocSize,
848 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
849 :
850 E : ASSERT_TRUE(tester.memory_error_detected());
851 E : }
852 E : }
853 :
854 : void TestMemoryInterceptors::TestUnderrunAccess(
855 E : const InterceptFunction* fns, size_t num_fns) {
856 E : for (size_t i = 0; i < num_fns; ++i) {
857 E : const InterceptFunction& fn = fns[i];
858 :
859 : // TODO(someone): the 32 byte access checker does not fire on 32 byte
860 : // underrun. I guess the checkers test a single shadow byte at most
861 : // whereas it'd be more correct for access checkers to test as many
862 : // shadow bytes as is appropriate for the range of memory they touch.
863 E : MemoryAccessorTester tester;
864 : tester.AssertMemoryErrorIsDetected(
865 : reinterpret_cast<FARPROC>(fn.function),
866 : src_ - 8,
867 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_UNDERFLOW);
868 :
869 E : ASSERT_TRUE(tester.memory_error_detected());
870 E : }
871 E : }
872 :
873 : void TestMemoryInterceptors::TestUnderrunAccessIgnoreFlags(
874 E : const InterceptFunction* fns, size_t num_fns) {
875 E : for (size_t i = 0; i < num_fns; ++i) {
876 E : const InterceptFunction& fn = fns[i];
877 :
878 : // TODO(someone): the 32 byte access checker does not fire on 32 byte
879 : // underrun. I guess the checkers test a single shadow byte at most
880 : // whereas it'd be more correct for access checkers to test as many
881 : // shadow bytes as is appropriate for the range of memory they touch.
882 E : MemoryAccessorTester tester(MemoryAccessorTester::IGNORE_FLAGS);
883 : tester.AssertMemoryErrorIsDetected(
884 : reinterpret_cast<FARPROC>(fn.function),
885 : src_ - 8,
886 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_UNDERFLOW);
887 :
888 E : ASSERT_TRUE(tester.memory_error_detected());
889 E : }
890 E : }
891 :
892 : void TestMemoryInterceptors::TestStringValidAccess(
893 E : const StringInterceptFunction* fns, size_t num_fns) {
894 E : for (size_t i = 0; i < num_fns; ++i) {
895 E : const StringInterceptFunction& fn = fns[i];
896 :
897 E : MemoryAccessorTester tester;
898 : tester.CheckSpecialAccessAndCompareContexts(
899 : reinterpret_cast<FARPROC>(fn.function),
900 : MemoryAccessorTester::DIRECTION_FORWARD,
901 E : dst_, src_, kAllocSize / fn.size);
902 E : ASSERT_FALSE(tester.memory_error_detected());
903 :
904 : tester.CheckSpecialAccessAndCompareContexts(
905 : reinterpret_cast<FARPROC>(fn.function),
906 : MemoryAccessorTester::DIRECTION_BACKWARD,
907 : dst_ + kAllocSize - fn.size, src_ + kAllocSize - fn.size,
908 E : kAllocSize / fn.size);
909 :
910 E : ASSERT_FALSE(tester.memory_error_detected());
911 E : }
912 E : }
913 :
914 : void TestMemoryInterceptors::TestStringOverrunAccess(
915 E : const StringInterceptFunction* fns, size_t num_fns) {
916 E : for (size_t i = 0; i < num_fns; ++i) {
917 E : const StringInterceptFunction& fn = fns[i];
918 :
919 E : MemoryAccessorTester tester;
920 E : size_t oob_len = 0;
921 E : byte* oob_dst = NULL;
922 E : byte* oob_src = NULL;
923 :
924 : // Half the string function intercepts are for rep-prefixed instructions,
925 : // which count on "ecx", and the other half is for non-prefixed
926 : // instructions that always perform a single access.
927 : // Compute appropriate pointers for both variants, forwards.
928 E : if (fn.uses_counter) {
929 E : oob_len = kAllocSize / fn.size;
930 E : oob_dst = dst_ + fn.size;
931 E : oob_src = src_ + fn.size;
932 E : } else {
933 E : oob_len = 1;
934 E : oob_dst = dst_ + kAllocSize;
935 E : oob_src = src_ + kAllocSize;
936 : }
937 :
938 E : ASSERT_NE(agent::asan::ASAN_UNKNOWN_ACCESS, fn.dst_access_mode);
939 : // Overflow on dst forwards.
940 : tester.ExpectSpecialMemoryErrorIsDetected(
941 : reinterpret_cast<FARPROC>(fn.function),
942 : MemoryAccessorTester::DIRECTION_FORWARD, true,
943 : oob_dst, src_, oob_len,
944 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
945 :
946 E : if (fn.src_access_mode != agent::asan::ASAN_UNKNOWN_ACCESS) {
947 : // Overflow on src forwards.
948 : tester.ExpectSpecialMemoryErrorIsDetected(
949 : reinterpret_cast<FARPROC>(fn.function),
950 : MemoryAccessorTester::DIRECTION_FORWARD, true,
951 : dst_, oob_src, oob_len,
952 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
953 : }
954 :
955 : // Compute appropriate pointers for both variants, backwards.
956 E : if (fn.uses_counter) {
957 E : oob_len = kAllocSize / fn.size;
958 E : } else {
959 E : oob_len = 1;
960 : }
961 :
962 E : oob_dst = dst_ + kAllocSize;
963 E : oob_src = src_ + kAllocSize;
964 :
965 E : ASSERT_NE(agent::asan::ASAN_UNKNOWN_ACCESS, fn.dst_access_mode);
966 : // Overflow on dst backwards.
967 : tester.ExpectSpecialMemoryErrorIsDetected(
968 : reinterpret_cast<FARPROC>(fn.function),
969 : MemoryAccessorTester::DIRECTION_BACKWARD, true,
970 : oob_dst, src_ + kAllocSize - fn.size, oob_len,
971 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
972 :
973 E : if (fn.src_access_mode != agent::asan::ASAN_UNKNOWN_ACCESS) {
974 : // Overflow on src backwards.
975 : tester.ExpectSpecialMemoryErrorIsDetected(
976 : reinterpret_cast<FARPROC>(fn.function),
977 : MemoryAccessorTester::DIRECTION_BACKWARD, true,
978 : dst_ + kAllocSize - fn.size, oob_dst, oob_len,
979 E : MemoryAccessorTester::BadAccessKind::HEAP_BUFFER_OVERFLOW);
980 : }
981 E : }
982 E : }
983 :
984 E : bool IsAccessible(void* address) {
985 E : return testing::TestAccess(address, false);
986 E : }
987 :
988 E : bool IsNotAccessible(void* address) {
989 E : return testing::TestAccess(address, true);
990 E : }
991 :
992 : } // namespace testing
|