Coverage for /Syzygy/agent/asan/rtl_utils.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
97.2%70720.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 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_utils.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/heap_checker.h"
  23    :  #include "syzygy/agent/asan/runtime.h"
  24    :  #include "syzygy/agent/asan/shadow.h"
  25    :  #include "syzygy/agent/common/scoped_last_error_keeper.h"
  26    :  #include "syzygy/agent/common/stack_capture.h"
  27    :  
  28    :  namespace {
  29    :  
  30    :  // The asan runtime manager.
  31    :  agent::asan::AsanRuntime* asan_runtime = NULL;
  32    :  
  33    :  }  // namespace
  34    :  
  35    :  namespace agent {
  36    :  namespace asan {
  37    :  
  38  E :  void SetAsanRuntimeInstance(AsanRuntime* runtime) {
  39  E :    asan_runtime = runtime;
  40  E :  }
  41    :  
  42    :  void ReportBadMemoryAccess(void* location,
  43    :                             AccessMode access_mode,
  44    :                             size_t access_size,
  45  E :                             const AsanContext& asan_context) {
  46    :    // Capture the context and restore the value of the register as before calling
  47    :    // the asan hook.
  48    :  
  49    :    // Save the last error value so this function will be able to restore it.
  50  E :    agent::common::ScopedLastErrorKeeper scoped_last_error_keeper;
  51    :  
  52    :    // We keep a structure with all the useful information about this bad access
  53    :    // on the stack.
  54  E :    AsanErrorInfo bad_access_info = {};
  55    :  
  56    :    // We need to call ::RtlCaptureContext if we want SegSS and SegCS to be
  57    :    // properly set.
  58  E :    ::RtlCaptureContext(&bad_access_info.context);
  59  E :    bad_access_info.context.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
  60    :  
  61    :    // Restore the original value of the registers.
  62  E :    bad_access_info.context.Eip = asan_context.original_eip;
  63  E :    bad_access_info.context.Eax = asan_context.original_eax;
  64  E :    bad_access_info.context.Ecx = asan_context.original_ecx;
  65  E :    bad_access_info.context.Edx = asan_context.original_edx;
  66  E :    bad_access_info.context.Ebx = asan_context.original_ebx;
  67  E :    bad_access_info.context.Ebp = asan_context.original_ebp;
  68  E :    bad_access_info.context.Esp = asan_context.original_esp;
  69  E :    bad_access_info.context.Esi = asan_context.original_esi;
  70  E :    bad_access_info.context.Edi = asan_context.original_edi;
  71  E :    bad_access_info.context.EFlags = asan_context.original_eflags;
  72    :  
  73  E :    common::StackCapture stack;
  74  E :    stack.InitFromStack();
  75    :    // We need to use the relative stack id so that for the same stack trace we
  76    :    // get the same value every time even if the modules are loaded at a different
  77    :    // base address.
  78    :    //
  79    :    // Check if we can ignore this error.
  80  E :    if (asan_runtime->ShouldIgnoreError(stack.relative_stack_id()))
  81  i :      return;
  82    :  
  83  E :    bad_access_info.crash_stack_id = stack.relative_stack_id();
  84  E :    bad_access_info.location = location;
  85  E :    bad_access_info.access_mode = access_mode;
  86  E :    bad_access_info.access_size = access_size;
  87  E :    bad_access_info.error_type = UNKNOWN_BAD_ACCESS;
  88  E :    bad_access_info.block_info.alloc_stack_size = 0U;
  89  E :    bad_access_info.block_info.alloc_tid = 0U;
  90  E :    bad_access_info.block_info.free_stack_size = 0U;
  91  E :    bad_access_info.block_info.free_tid = 0U;
  92  E :    bad_access_info.block_info.milliseconds_since_free = 0U;
  93  E :    bad_access_info.corrupt_ranges = NULL;
  94  E :    bad_access_info.corrupt_range_count = 0;
  95    :  
  96    :    // Make sure this structure is not optimized out.
  97  E :    base::debug::Alias(&bad_access_info);
  98    :  
  99    :    // TODO(sebmarchand): Check if the heap is corrupt and store the information
 100    :    //     about the corrupt blocks if it's the case.
 101  E :    bad_access_info.heap_is_corrupt = false;
 102    :  
 103  E :    asan_runtime->GetBadAccessInformation(&bad_access_info);
 104    :  
 105    :    // Accesses to the first 64k of the memory (invalid address) should not be
 106    :    // reported by SyzyASAN unless we detect a heap corruption or if it has been
 107    :    // requested by the user. By returning early, we let the unhandled exception
 108    :    // filter do the heap corruption check. The check is not done here because we
 109    :    // don't want to duplicate the work.
 110    :    if (!asan_runtime->params().report_invalid_accesses &&
 111    :        bad_access_info.location <
 112  E :            reinterpret_cast<void*>(Shadow::kAddressLowerBound)) {
 113  E :      return;
 114    :    }
 115    :  
 116    :    // Report this error.
 117  E :    asan_runtime->OnError(&bad_access_info);
 118  E :  }
 119    :  
 120  E :  void ContextToAsanContext(const CONTEXT& context, AsanContext* asan_context) {
 121  E :    DCHECK(asan_context != NULL);
 122  E :    asan_context->original_eax = context.Eax;
 123  E :    asan_context->original_ebp = context.Ebp;
 124  E :    asan_context->original_ebx = context.Ebx;
 125  E :    asan_context->original_ecx = context.Ecx;
 126  E :    asan_context->original_edi = context.Edi;
 127  E :    asan_context->original_edx = context.Edx;
 128  E :    asan_context->original_eflags = context.EFlags;
 129  E :    asan_context->original_eip = context.Eip;
 130  E :    asan_context->original_esi = context.Esi;
 131  E :    asan_context->original_esp = context.Esp;
 132  E :  }
 133    :  
 134  E :  void ReportBadAccess(const uint8* location, AccessMode access_mode) {
 135  E :    AsanContext asan_context = {};
 136  E :    CONTEXT context = {};
 137  E :    ::RtlCaptureContext(&context);
 138  E :    ContextToAsanContext(context, &asan_context);
 139    :    ReportBadMemoryAccess(const_cast<uint8*>(location), access_mode, 1U,
 140  E :                          asan_context);
 141  E :  }
 142    :  
 143    :  void TestMemoryRange(Shadow* shadow,
 144    :                       const uint8* memory,
 145    :                       size_t size,
 146  E :                       AccessMode access_mode) {
 147  E :    if (!shadow || size == 0U)
 148  i :      return;
 149    :  
 150    :    // TODO(sebmarchand): This approach is pretty limited because it only checks
 151    :    //     if the first and the last elements are accessible. Once we have the
 152    :    //     plumbing in place we should benchmark a check that looks at each
 153    :    //     address to be touched (via the shadow memory, 8 bytes at a time).
 154    :    if (!shadow->IsAccessible(memory) ||
 155  E :        !shadow->IsAccessible(memory + size - 1)) {
 156  E :      const uint8* location = NULL;
 157  E :      if (!shadow->IsAccessible(memory)) {
 158  E :        location = memory;
 159  E :      } else {
 160  E :        location = memory + size - 1;
 161    :      }
 162  E :      ReportBadAccess(location, access_mode);
 163    :    }
 164  E :  }
 165    :  
 166    :  }  // namespace asan
 167    :  }  // namespace agent

Coverage information generated Thu Jan 14 17:40:38 2016.