File: crash_analyzer.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (138 lines) | stat: -rw-r--r-- 5,763 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_GWP_ASAN_CRASH_HANDLER_CRASH_ANALYZER_H_
#define COMPONENTS_GWP_ASAN_CRASH_HANDLER_CRASH_ANALYZER_H_

#include <stddef.h>

#include "base/gtest_prod_util.h"
#include "components/gwp_asan/common/allocation_info.h"
#include "components/gwp_asan/common/allocator_state.h"
#include "components/gwp_asan/common/lightweight_detector_state.h"
#include "components/gwp_asan/crash_handler/crash.pb.h"
#include "third_party/crashpad/crashpad/util/misc/address_types.h"

namespace crashpad {
class ExceptionSnapshot;
class ProcessMemory;
class ProcessSnapshot;
}  // namespace crashpad

namespace gwp_asan {
namespace internal {

// Captures the result of the GWP-ASan crash analyzer, whether the crash is
// determined to be related or unrelated to GWP-ASan or if an error was
// encountered analyzing the exception.
//
// These values are persisted via UMA--entries should not be renumbered and
// numeric values should never be reused.
enum class GwpAsanCrashAnalysisResult {
  // The crash is not caused by GWP-ASan.
  kUnrelatedCrash = 0,
  // The crash is caused by GWP-ASan.
  kGwpAsanCrash = 1,
  // The ProcessMemory from the snapshot was null.
  kErrorNullProcessMemory = 2,
  // Failed to read the crashing process' memory of the global allocator.
  kErrorFailedToReadAllocator = 3,
  // The crashing process' global allocator members failed sanity checks.
  kErrorAllocatorFailedSanityCheck = 4,
  // Failed to read crash stack traces.
  kErrorFailedToReadStackTrace = 5,
  // The ExceptionSnapshot CPU context was null.
  kErrorNullCpuContext = 6,
  // The crashing process' bitness does not match the crash handler.
  kErrorMismatchedBitness = 7,
  // The allocator computed an invalid slot index.
  kErrorBadSlot = 8,
  // Failed to read the crashing process' memory of the SlotMetadata.
  kErrorFailedToReadSlotMetadata = 9,
  // The allocator stored an invalid metadata index for a given slot.
  kErrorBadMetadataIndex = 10,
  // The computed metadata index was outdated.
  kErrorOutdatedMetadataIndex = 11,
  // Failed to read the crashing process' slot to metadata mapping.
  kErrorFailedToReadSlotMetadataMapping = 12,

  // The crash is caused by the Lightweight UAF Detector.
  kLightweightDetectorCrash = 13,
  // Failed to read the crashing process' memory of the Lightweight UAF Detector
  // metadata store.
  kErrorFailedToReadLightweightSlotMetadata = 14,
  // The computed lightweight metadata index was invalid or outdated.
  kErrorInvalidOrOutdatedLightweightMetadataIndex = 15,
  // The crashing process' architecture does not match the crash handler.
  kErrorMismatchedCpuArchitecture = 16,
  // Found conflicting lightweight metadata IDs.
  kErrorConflictingLightweightMetadataIds = 17,

  // Number of values in this enumeration, required by UMA.
  kMaxValue = kErrorConflictingLightweightMetadataIds
};

class CrashAnalyzer {
 public:
  // Given a ProcessSnapshot, determine if the exception is related to GWP-ASan.
  // If it is, returns true and fill out the |proto| parameter with details
  // about the exception. Otherwise, returns false.
  static bool GetExceptionInfo(
      const crashpad::ProcessSnapshot& process_snapshot,
      gwp_asan::Crash* proto);

 private:
  // Given an ExceptionSnapshot, return the address of where the exception
  // occurred (or null if it was not a data access exception.)
  static crashpad::VMAddress GetAccessAddress(
      const crashpad::ExceptionSnapshot& exception);

  // If the allocator annotation is present in the given snapshot, then return
  // the address for the AllocatorState in the crashing process.
  static crashpad::VMAddress GetStateAddress(
      const crashpad::ProcessSnapshot& process_snapshot,
      const char* annotation_name);

  // Given a snapshot and crash key, returns true if there was a valid
  // `AllocatorState` or `LightweightDetectorState` or false otherwise.
  template <typename T>
  static bool GetState(const crashpad::ProcessSnapshot& process_snapshot,
                       const char* crash_key,
                       Crash_Allocator allocator,
                       T* state);

  // This method implements the underlying logic for GetExceptionInfo(). It
  // analyzes the AllocatorState of the crashing process, if the exception is
  // related to GWP-ASan it fills out the |proto| parameter and returns true.
  static bool AnalyzeCrashedAllocator(
      const crashpad::ProcessSnapshot& process_snapshot,
      const char* crash_key,
      Crash_Allocator allocator,
      gwp_asan::Crash* proto);

  // This method fills out an AllocationInfo protobuf from a stack trace
  // and a AllocatorState::AllocationInfo struct.
  static void ReadAllocationInfo(const uint8_t* stack_trace,
                                 size_t stack_trace_offset,
                                 const AllocationInfo& slot_info,
                                 gwp_asan::Crash_AllocationInfo* proto_info);

  // This method analyzes the AllocatorState of the crashing process. If the
  // exception is related to the Lightweight UAF Detector it fills out the
  // |proto| parameter and returns true.
  static bool AnalyzeLightweightDetectorCrash(
      const crashpad::ProcessSnapshot& process_snapshot,
      gwp_asan::Crash* proto);

  static Crash_Mode LightweightDetectorModeToGwpAsanMode(
      LightweightDetectorMode mode);

  FRIEND_TEST_ALL_PREFIXES(LightweightDetectorAnalyzerTest, UseAfterFree);
  FRIEND_TEST_ALL_PREFIXES(LightweightDetectorAnalyzerTest, InternalError);
};

}  // namespace internal
}  // namespace gwp_asan

#endif  // COMPONENTS_GWP_ASAN_CRASH_HANDLER_CRASH_ANALYZER_H_