Coverage for /Syzygy/agent/asan/error_info.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%330.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    :  // Declares structures and utility functions used to get information about an
  16    :  // Asan error.
  17    :  
  18    :  #ifndef SYZYGY_AGENT_ASAN_ERROR_INFO_H_
  19    :  #define SYZYGY_AGENT_ASAN_ERROR_INFO_H_
  20    :  
  21    :  #include <utility>
  22    :  #include <vector>
  23    :  
  24    :  #include "base/callback.h"
  25    :  #include "syzygy/agent/asan/block.h"
  26    :  #include "syzygy/agent/asan/heap.h"
  27    :  #include "syzygy/agent/common/stack_capture.h"
  28    :  #include "syzygy/common/asan_parameters.h"
  29    :  
  30    :  // Forward declaration.
  31    :  namespace crashdata {
  32    :  class Value;
  33    :  }  // namespace crashdata
  34    :  
  35    :  namespace agent {
  36    :  namespace asan {
  37    :  
  38    :  // Forward declarations.
  39    :  class Shadow;
  40    :  class StackCaptureCache;
  41    :  struct BlockHeader;
  42    :  
  43    :  // The different memory access modes that we can encounter.
  44    :  enum AccessMode {
  45    :    ASAN_READ_ACCESS,
  46    :    ASAN_WRITE_ACCESS,
  47    :    ASAN_UNKNOWN_ACCESS,
  48    :  
  49    :    ASAN_ACCESS_MODE_MAX,
  50    :  };
  51    :  
  52    :  // Enumeration of the different kinds of bad heap accesses that we can
  53    :  // encounter.
  54    :  enum BadAccessKind {
  55    :    // This enum should start with bad access type that are not relative to a
  56    :    // heap block.
  57    :    // @note The ordering is important because those labels are used in
  58    :    //     numeric inequalities.
  59    :    UNKNOWN_BAD_ACCESS,
  60    :    WILD_ACCESS,
  61    :    INVALID_ADDRESS,
  62    :    CORRUPT_BLOCK,
  63    :    CORRUPT_HEAP,
  64    :  
  65    :    // This enum should end with bad access types that are relative to heap
  66    :    // blocks.
  67    :    USE_AFTER_FREE,
  68    :    HEAP_BUFFER_OVERFLOW,
  69    :    HEAP_BUFFER_UNDERFLOW,
  70    :    DOUBLE_FREE,
  71    :  
  72    :    BAD_ACCESS_KIND_MAX,
  73    :  };
  74    :  
  75    :  // The different types of errors we can encounter.
  76    :  extern const char kHeapUseAfterFree[];
  77    :  extern const char kHeapBufferUnderFlow[];
  78    :  extern const char kHeapBufferOverFlow[];
  79    :  extern const char kAttemptingDoubleFree[];
  80    :  extern const char kInvalidAddress[];
  81    :  extern const char kWildAccess[];
  82    :  extern const char kHeapUnknownError[];
  83    :  extern const char kHeapCorruptBlock[];
  84    :  extern const char kCorruptHeap[];
  85    :  
  86    :  enum AsanFeature : uint32_t {
  87    :    ASAN_FEATURE_ENABLE_PAGE_PROTECTIONS = (1 << 0),
  88    :    // This feature flag is currently deprecated and ignored.
  89    :    DEPRECATED_ASAN_FEATURE_ENABLE_CTMALLOC = (1 << 1),
  90    :    ASAN_FEATURE_ENABLE_LARGE_BLOCK_HEAP = (1 << 2),
  91    :    // This feature flag is currently deprecated and ignored.
  92    :    DEPRECATED_ASAN_FEATURE_ENABLE_KASKO = (1 << 3),
  93    :    ASAN_FEATURE_ENABLE_CRASHPAD = (1 << 4),
  94    :    ASAN_FEATURE_MAX = (1 << 5),
  95    :  };
  96    :  using AsanFeatureSet = uint32_t;
  97    :  
  98    :  // Feature set for all valid features.
  99    :  const AsanFeatureSet kAsanValidFeatures =
 100    :      ASAN_FEATURE_ENABLE_PAGE_PROTECTIONS |
 101    :      ASAN_FEATURE_ENABLE_LARGE_BLOCK_HEAP | ASAN_FEATURE_ENABLE_CRASHPAD;
 102    :  
 103    :  // Feature set for all deprecated features.
 104    :  const AsanFeatureSet kAsanDeprecatedFeatures =
 105    :      DEPRECATED_ASAN_FEATURE_ENABLE_CTMALLOC |
 106    :      DEPRECATED_ASAN_FEATURE_ENABLE_KASKO;
 107    :  
 108    :  // Store the information that we want to report about a block.
 109    :  // TODO(sebmarchand): Rename this to avoid the confusion with the BlockInfo
 110    :  //     structure?
 111    :  struct AsanBlockInfo {
 112    :    // The address of the header for this block.
 113    :    const void* header;
 114    :    // The user size of the block.
 115    :    size_t user_size : 30;
 116    :    // This is implicitly a BlockState value.
 117    :    size_t state : 2;
 118    :    // The ID of the allocation thread.
 119    :    DWORD alloc_tid;
 120    :    // The ID of the free thread.
 121    :    DWORD free_tid;
 122    :    // The result of a block analysis on this block.
 123    :    BlockAnalysisResult analysis;
 124    :    // The allocation stack trace.
 125    :    void* alloc_stack[agent::common::StackCapture::kMaxNumFrames];
 126    :    // The free stack trace.
 127    :    void* free_stack[agent::common::StackCapture::kMaxNumFrames];
 128    :    // The size of the allocation stack trace.
 129    :    uint8_t alloc_stack_size;
 130    :    // The size of the free stack trace.
 131    :    uint8_t free_stack_size;
 132    :    // The type of heap that made the allocation.
 133    :    HeapType heap_type;
 134    :    // The time since this block has been freed. This would be equal to zero if
 135    :    // the block is still allocated.
 136    :    // TODO(chrisha): We actually keep track of this in ticks. Rename this?
 137    :    uint32_t milliseconds_since_free;
 138    :  };
 139    :  
 140    :  struct AsanCorruptBlockRange {
 141    :    // The beginning address of the range.
 142    :    const void* address;
 143    :    // The length of the range.
 144    :    size_t length;
 145    :    // The number of blocks in this range.
 146    :    size_t block_count;
 147    :    // The number of blocks in the |block_info| array.
 148    :    size_t block_info_count;
 149    :    // The information about the blocks in this range. This may include one or
 150    :    // more of the corrupt blocks and/or the valid blocks surrounding them; at the
 151    :    // very least it will contain the first corrupt block in the range. The real
 152    :    // length of this array will be stored in |block_info_count|. The array itself
 153    :    // is allocated on the stack so that it gets shipped with minidumps.
 154    :    AsanBlockInfo* block_info;
 155    :  };
 156    :  
 157    :  // Store the information about a bad memory access.
 158    :  struct AsanErrorInfo {
 159    :    // The address where the bad access happened.
 160    :    const void* location;
 161    :    // The context prior to the crash.
 162    :    CONTEXT context;
 163    :    // The ID of the crash stack, this is needed to be able to blacklist some
 164    :    // known bugs.
 165    :    common::StackCapture::StackId crash_stack_id;
 166    :    // The information about the block that contains the invalid location.
 167    :    AsanBlockInfo block_info;
 168    :    // The error type.
 169    :    BadAccessKind error_type;
 170    :    // The access mode.
 171    :    AccessMode access_mode;
 172    :    // The access size.
 173    :    size_t access_size;
 174    :    // The information about the shadow memory for this address, this would be
 175    :    // something like: "0x12345678 is located 8 bytes inside of a 10-byte region
 176    :    // [0x12345670,0x1234567A)."
 177    :    char shadow_info[128];
 178    :    // A textual description of the shadow memory around |location|.
 179    :    char shadow_memory[512];
 180    :    // Indicates if the heap is corrupt.
 181    :    bool heap_is_corrupt;
 182    :    // The number of corrupt ranges encountered.
 183    :    size_t corrupt_range_count;
 184    :    // The number of corrupt blocks encountered.
 185    :    size_t corrupt_block_count;
 186    :    // The number of corrupt ranges reported in |corrupt_ranges|.
 187    :    size_t corrupt_ranges_reported;
 188    :    // The information about the corrupt ranges of memory. The real length of this
 189    :    // array will be stored in |corrupt_ranges_reported|. This will be NULL if
 190    :    // |corrupt_ranges_reported| is zero.
 191    :    AsanCorruptBlockRange* corrupt_ranges;
 192    :    // The current configuration of the runtime library.
 193    :    ::common::AsanParameters asan_parameters;
 194    :    // Temporarily report the list of features that have been randomly enabled for
 195    :    // this client. This is something that could be deduced by analyzing the
 196    :    // |asan_parameters| structure but having it directly available in the crash
 197    :    // report structure will make it easier to investigate on the heap corruption
 198    :    // bug that we're tracking.
 199    :    // TODO(sebmarchand): Remove this once we don't need it anymore.
 200    :    AsanFeatureSet feature_set;
 201    :  };
 202    :  
 203    :  // Helper struct that is used when calculating the range of the shadow memory
 204    :  // surrounding a point of invalid access.
 205    :  struct AsanErrorShadowMemory {
 206    :    uintptr_t index;
 207    :    uintptr_t address;
 208    :    uintptr_t length;
 209    :  };
 210    :  
 211    :  // This callback allows a heap manager to report heap consistency problems that
 212    :  // it encounters during its operation. This is usually plumbed into the Asan
 213    :  // runtime so that the errors may be appropriately reported.
 214    :  //
 215    :  // |asan_error_info| contains information about the primary heap error that
 216    :  // was encountered. It is guaranteed to be on the stack.
 217    :  typedef base::Callback<void(AsanErrorInfo* asan_error_info)>
 218    :      HeapErrorCallback;
 219    :  
 220    :  // Contains pairs of address/size of data to be reported to Kasko during a
 221    :  // crash.
 222    :  typedef std::vector<std::pair<const char*, size_t>> MemoryRanges;
 223    :  
 224    :  // Returns a string describing a bad access kind.
 225    :  // @param bad_access_kind The bad access kind for which we want a textual
 226    :  //     representation.
 227    :  // @returns a string describing the bad access kind.
 228    :  const char* ErrorInfoAccessTypeToStr(BadAccessKind bad_access_kind);
 229    :  
 230    :  // Get information about a bad access.
 231    :  // @param shadow The shadow memory to query.
 232    :  // @param stack_cache The stack cache that owns the alloc and free stack traces
 233    :  //     of the blocks.
 234    :  // @param bad_access_info Will receive the information about this access.
 235    :  // @returns true if the address belongs to a memory block, false otherwise.
 236    :  bool ErrorInfoGetBadAccessInformation(const Shadow* shadow,
 237    :                                        StackCaptureCache* stack_cache,
 238    :                                        AsanErrorInfo* bad_access_info);
 239    :  
 240    :  // Give the type of a bad heap access corresponding to an address.
 241    :  // @param shadow The shadow memory to query.
 242    :  // @param addr The address causing a bad heap access.
 243    :  // @param header The header of the block containing this address.
 244    :  // @returns The type of the bad heap access corresponding to this address.
 245    :  // @note Exposed for unittesting.
 246    :  BadAccessKind ErrorInfoGetBadAccessKind(const Shadow* shadow,
 247    :                                          const void* addr,
 248    :                                          const BlockHeader* header);
 249    :  
 250    :  // Retrieves a block's metadata.
 251    :  // @param shadow The shadow memory to query.
 252    :  // @param block_info The block whose info is to be gathered.
 253    :  // @param stack_cache The stack cache that owns the alloc and free stack traces
 254    :  //     of this block.
 255    :  // @param asan_block_info Will receive the block's metadata.
 256    :  void ErrorInfoGetAsanBlockInfo(const Shadow* shadow,
 257    :                                 const BlockInfo& block_info,
 258    :                                 StackCaptureCache* stack_cache,
 259    :                                 AsanBlockInfo* asan_block_info);
 260    :  
 261    :  // Computes the range of the shadow memory surrounding the point of invalid
 262    :  // access.
 263    :  // @param shadow The shadow memory to query.
 264    :  // @param error_location The memory location where the error occured.
 265    :  // @param shadow_memory Will receive the shadow memory surrounding the error.
 266    :  void GetAsanErrorShadowMemory(const Shadow* shadow,
 267    :                                const void* error_location,
 268    :                                AsanErrorShadowMemory* shadow_memory);
 269    :  
 270    :  // Given a populated AsanBlockInfo struct, fills out a corresponding crashdata
 271    :  // protobuf.
 272    :  // @param shadow The shadow memory to query.
 273    :  // @param block_info The block info information.
 274    :  // @param include_block_contents If this is true the block contents will be
 275    :  //     explicitly included in the protobuf.
 276    :  // @param value The uninitialized protobuf value to be populated.
 277    :  // @param memory_ranges If its value is not nullptr, the address/size of
 278    :  //     relevant memory content will be appended to this variable.
 279    :  void PopulateBlockInfo(const Shadow* shadow,
 280    :                         const AsanBlockInfo& block_info,
 281    :                         bool include_block_contents,
 282    :                         crashdata::Value* value,
 283    :                         MemoryRanges* memory_ranges);
 284    :  
 285    :  // Given a populated AsanCorruptBlockRange struct, fills out a corresponding
 286    :  // crashdata protobuf.
 287    :  // @param shadow The shadow memory to query.
 288    :  // @param range The corrupt block range information.
 289    :  // @param value The uninitialized protobuf value to be populated.
 290    :  // @param memory_ranges If its value is not nullptr, the address/size of
 291    :  //     relevant memory content will be appended to this variable.
 292    :  void PopulateCorruptBlockRange(const Shadow* shadow,
 293    :                                 const AsanCorruptBlockRange& range,
 294    :                                 crashdata::Value* value,
 295    :                                 MemoryRanges* memory_ranges);
 296    :  
 297    :  // Given a populated AsanErrorInfo struct, fills out a corresponding crashdata
 298    :  // protobuf.
 299    :  // @param shadow The shadow memory to query.
 300    :  // @param error_info The filled in error information.
 301    :  // @param value The uninitialized protobuf value to be populated.
 302    :  // @param memory_ranges If its value is not nullptr, the address/size of
 303    :  //     relevant memory content will be appended to this variable.
 304    :  void PopulateErrorInfo(const Shadow* shadow,
 305    :                         const AsanErrorInfo& error_info,
 306    :                         crashdata::Value* value,
 307    :                         MemoryRanges* memory_ranges);
 308    :  
 309    :  // Given a populated crashdata protobuf, fills out a corresponding AsanErrorInfo
 310    :  // struct.
 311    :  // @param protobuf The filled in error information protobuf.
 312    :  // @param value The uninitialized AsanErrorInfo struct to be populated.
 313    :  void CrashdataProtobufToErrorInfo(const crashdata::Value& protobuf,
 314    :                                    AsanErrorInfo* error_info);
 315    :  
 316    :  // Helper function to get the instruction pointer from a CONTEXT
 317    :  // on both ia32 and x64.
 318  E :  inline void* GetInstructionPointer(const CONTEXT& context) {
 319    :  #ifdef _WIN64
 320    :    return reinterpret_cast<void*>(context.Rip);
 321    :  #else
 322  E :    return reinterpret_cast<void*>(context.Eip);
 323    :  #endif
 324  E :  }
 325    :  
 326    :  }  // namespace asan
 327    :  }  // namespace agent
 328    :  
 329    :  #endif  // SYZYGY_AGENT_ASAN_ERROR_INFO_H_

Coverage information generated Fri Jul 29 11:00:21 2016.