xref: /aosp_15_r20/external/google-breakpad/src/processor/exploitability_linux.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle // Copyright 2013 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle //     * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle //     * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle //     * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle 
29*9712c20fSFrederick Mayle // exploitability_linux.cc: Linux specific exploitability engine.
30*9712c20fSFrederick Mayle //
31*9712c20fSFrederick Mayle // Provides a guess at the exploitability of the crash for the Linux
32*9712c20fSFrederick Mayle // platform given a minidump and process_state.
33*9712c20fSFrederick Mayle //
34*9712c20fSFrederick Mayle // Author: Matthew Riley
35*9712c20fSFrederick Mayle 
36*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
37*9712c20fSFrederick Mayle #include <config.h>  // Must come first
38*9712c20fSFrederick Mayle #endif
39*9712c20fSFrederick Mayle 
40*9712c20fSFrederick Mayle #include "processor/exploitability_linux.h"
41*9712c20fSFrederick Mayle 
42*9712c20fSFrederick Mayle #include <string.h>
43*9712c20fSFrederick Mayle 
44*9712c20fSFrederick Mayle #include "google_breakpad/common/minidump_exception_linux.h"
45*9712c20fSFrederick Mayle #include "google_breakpad/processor/call_stack.h"
46*9712c20fSFrederick Mayle #include "google_breakpad/processor/process_state.h"
47*9712c20fSFrederick Mayle #include "google_breakpad/processor/stack_frame.h"
48*9712c20fSFrederick Mayle #ifdef __linux__
49*9712c20fSFrederick Mayle #include "processor/disassembler_objdump.h"
50*9712c20fSFrederick Mayle #endif
51*9712c20fSFrederick Mayle #include "processor/logging.h"
52*9712c20fSFrederick Mayle 
53*9712c20fSFrederick Mayle namespace {
54*9712c20fSFrederick Mayle 
55*9712c20fSFrederick Mayle // Prefixes for memory mapping names.
56*9712c20fSFrederick Mayle constexpr char kHeapPrefix[] = "[heap";
57*9712c20fSFrederick Mayle constexpr char kStackPrefix[] =  "[stack";
58*9712c20fSFrederick Mayle 
59*9712c20fSFrederick Mayle // This function in libc is called if the program was compiled with
60*9712c20fSFrederick Mayle // -fstack-protector and a function's stack canary changes.
61*9712c20fSFrederick Mayle constexpr char kStackCheckFailureFunction[] = "__stack_chk_fail";
62*9712c20fSFrederick Mayle 
63*9712c20fSFrederick Mayle // This function in libc is called if the program was compiled with
64*9712c20fSFrederick Mayle // -D_FORTIFY_SOURCE=2, a function like strcpy() is called, and the runtime
65*9712c20fSFrederick Mayle // can determine that the call would overflow the target buffer.
66*9712c20fSFrederick Mayle constexpr char kBoundsCheckFailureFunction[] = "__chk_fail";
67*9712c20fSFrederick Mayle 
68*9712c20fSFrederick Mayle }  // namespace
69*9712c20fSFrederick Mayle 
70*9712c20fSFrederick Mayle namespace google_breakpad {
71*9712c20fSFrederick Mayle 
ExploitabilityLinux(Minidump * dump,ProcessState * process_state)72*9712c20fSFrederick Mayle ExploitabilityLinux::ExploitabilityLinux(Minidump* dump,
73*9712c20fSFrederick Mayle                                          ProcessState* process_state)
74*9712c20fSFrederick Mayle     : Exploitability(dump, process_state),
75*9712c20fSFrederick Mayle       enable_objdump_(false) { }
76*9712c20fSFrederick Mayle 
ExploitabilityLinux(Minidump * dump,ProcessState * process_state,bool enable_objdump)77*9712c20fSFrederick Mayle ExploitabilityLinux::ExploitabilityLinux(Minidump* dump,
78*9712c20fSFrederick Mayle                                          ProcessState* process_state,
79*9712c20fSFrederick Mayle                                          bool enable_objdump)
80*9712c20fSFrederick Mayle     : Exploitability(dump, process_state),
81*9712c20fSFrederick Mayle       enable_objdump_(enable_objdump) { }
82*9712c20fSFrederick Mayle 
83*9712c20fSFrederick Mayle 
CheckPlatformExploitability()84*9712c20fSFrederick Mayle ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() {
85*9712c20fSFrederick Mayle   // Check the crashing thread for functions suggesting a buffer overflow or
86*9712c20fSFrederick Mayle   // stack smash.
87*9712c20fSFrederick Mayle   if (process_state_->requesting_thread() != -1) {
88*9712c20fSFrederick Mayle     CallStack* crashing_thread =
89*9712c20fSFrederick Mayle         process_state_->threads()->at(process_state_->requesting_thread());
90*9712c20fSFrederick Mayle     const vector<StackFrame*>& crashing_thread_frames =
91*9712c20fSFrederick Mayle         *crashing_thread->frames();
92*9712c20fSFrederick Mayle     for (size_t i = 0; i < crashing_thread_frames.size(); ++i) {
93*9712c20fSFrederick Mayle       if (crashing_thread_frames[i]->function_name ==
94*9712c20fSFrederick Mayle           kStackCheckFailureFunction) {
95*9712c20fSFrederick Mayle         return EXPLOITABILITY_HIGH;
96*9712c20fSFrederick Mayle       }
97*9712c20fSFrederick Mayle 
98*9712c20fSFrederick Mayle       if (crashing_thread_frames[i]->function_name ==
99*9712c20fSFrederick Mayle           kBoundsCheckFailureFunction) {
100*9712c20fSFrederick Mayle         return EXPLOITABILITY_HIGH;
101*9712c20fSFrederick Mayle       }
102*9712c20fSFrederick Mayle     }
103*9712c20fSFrederick Mayle   }
104*9712c20fSFrederick Mayle 
105*9712c20fSFrederick Mayle   // Getting exception data. (It should exist for all minidumps.)
106*9712c20fSFrederick Mayle   MinidumpException* exception = dump_->GetException();
107*9712c20fSFrederick Mayle   if (exception == NULL) {
108*9712c20fSFrederick Mayle     BPLOG(INFO) << "No exception record.";
109*9712c20fSFrederick Mayle     return EXPLOITABILITY_ERR_PROCESSING;
110*9712c20fSFrederick Mayle   }
111*9712c20fSFrederick Mayle   const MDRawExceptionStream* raw_exception_stream = exception->exception();
112*9712c20fSFrederick Mayle   if (raw_exception_stream == NULL) {
113*9712c20fSFrederick Mayle     BPLOG(INFO) << "No raw exception stream.";
114*9712c20fSFrederick Mayle     return EXPLOITABILITY_ERR_PROCESSING;
115*9712c20fSFrederick Mayle   }
116*9712c20fSFrederick Mayle 
117*9712c20fSFrederick Mayle   // Checking for benign exceptions that caused the crash.
118*9712c20fSFrederick Mayle   if (this->BenignCrashTrigger(raw_exception_stream)) {
119*9712c20fSFrederick Mayle     return EXPLOITABILITY_NONE;
120*9712c20fSFrederick Mayle   }
121*9712c20fSFrederick Mayle 
122*9712c20fSFrederick Mayle   // Check if the instruction pointer is in a valid instruction region
123*9712c20fSFrederick Mayle   // by finding if it maps to an executable part of memory.
124*9712c20fSFrederick Mayle   uint64_t instruction_ptr = 0;
125*9712c20fSFrederick Mayle   uint64_t stack_ptr = 0;
126*9712c20fSFrederick Mayle 
127*9712c20fSFrederick Mayle   const MinidumpContext* context = exception->GetContext();
128*9712c20fSFrederick Mayle   if (context == NULL) {
129*9712c20fSFrederick Mayle     BPLOG(INFO) << "No exception context.";
130*9712c20fSFrederick Mayle     return EXPLOITABILITY_ERR_PROCESSING;
131*9712c20fSFrederick Mayle   }
132*9712c20fSFrederick Mayle 
133*9712c20fSFrederick Mayle   // Getting the instruction pointer.
134*9712c20fSFrederick Mayle   if (!context->GetInstructionPointer(&instruction_ptr)) {
135*9712c20fSFrederick Mayle     BPLOG(INFO) << "Failed to retrieve instruction pointer.";
136*9712c20fSFrederick Mayle     return EXPLOITABILITY_ERR_PROCESSING;
137*9712c20fSFrederick Mayle   }
138*9712c20fSFrederick Mayle 
139*9712c20fSFrederick Mayle   // Getting the stack pointer.
140*9712c20fSFrederick Mayle   if (!context->GetStackPointer(&stack_ptr)) {
141*9712c20fSFrederick Mayle     BPLOG(INFO) << "Failed to retrieve stack pointer.";
142*9712c20fSFrederick Mayle     return EXPLOITABILITY_ERR_PROCESSING;
143*9712c20fSFrederick Mayle   }
144*9712c20fSFrederick Mayle 
145*9712c20fSFrederick Mayle   // Checking for the instruction pointer in a valid instruction region,
146*9712c20fSFrederick Mayle   // a misplaced stack pointer, and an executable stack or heap.
147*9712c20fSFrederick Mayle   if (!this->InstructionPointerInCode(instruction_ptr) ||
148*9712c20fSFrederick Mayle        this->StackPointerOffStack(stack_ptr) ||
149*9712c20fSFrederick Mayle        this->ExecutableStackOrHeap()) {
150*9712c20fSFrederick Mayle     return EXPLOITABILITY_HIGH;
151*9712c20fSFrederick Mayle   }
152*9712c20fSFrederick Mayle 
153*9712c20fSFrederick Mayle   // Check for write to read only memory or invalid memory, shelling out
154*9712c20fSFrederick Mayle   // to objdump is enabled.
155*9712c20fSFrederick Mayle   if (enable_objdump_ && this->EndedOnIllegalWrite(instruction_ptr)) {
156*9712c20fSFrederick Mayle     return EXPLOITABILITY_HIGH;
157*9712c20fSFrederick Mayle   }
158*9712c20fSFrederick Mayle 
159*9712c20fSFrederick Mayle   // There was no strong evidence suggesting exploitability, but the minidump
160*9712c20fSFrederick Mayle   // does not appear totally benign either.
161*9712c20fSFrederick Mayle   return EXPLOITABILITY_INTERESTING;
162*9712c20fSFrederick Mayle }
163*9712c20fSFrederick Mayle 
EndedOnIllegalWrite(uint64_t instruction_ptr)164*9712c20fSFrederick Mayle bool ExploitabilityLinux::EndedOnIllegalWrite(uint64_t instruction_ptr) {
165*9712c20fSFrederick Mayle #ifndef __linux__
166*9712c20fSFrederick Mayle   BPLOG(INFO) << "MinGW does not support fork and exec. Terminating method.";
167*9712c20fSFrederick Mayle   return false;
168*9712c20fSFrederick Mayle #else
169*9712c20fSFrederick Mayle   // Get memory region containing instruction pointer.
170*9712c20fSFrederick Mayle   MinidumpMemoryList* memory_list = dump_->GetMemoryList();
171*9712c20fSFrederick Mayle   MinidumpMemoryRegion* memory_region =
172*9712c20fSFrederick Mayle       memory_list ?
173*9712c20fSFrederick Mayle       memory_list->GetMemoryRegionForAddress(instruction_ptr) : NULL;
174*9712c20fSFrederick Mayle   if (!memory_region) {
175*9712c20fSFrederick Mayle     BPLOG(INFO) << "No memory region around instruction pointer.";
176*9712c20fSFrederick Mayle     return false;
177*9712c20fSFrederick Mayle   }
178*9712c20fSFrederick Mayle 
179*9712c20fSFrederick Mayle   // Get exception data to find architecture.
180*9712c20fSFrederick Mayle   string architecture = "";
181*9712c20fSFrederick Mayle   MinidumpException* exception = dump_->GetException();
182*9712c20fSFrederick Mayle   // This should never evaluate to true, since this should not be reachable
183*9712c20fSFrederick Mayle   // without checking for exception data earlier.
184*9712c20fSFrederick Mayle   if (!exception) {
185*9712c20fSFrederick Mayle     BPLOG(INFO) << "No exception data.";
186*9712c20fSFrederick Mayle     return false;
187*9712c20fSFrederick Mayle   }
188*9712c20fSFrederick Mayle   const MDRawExceptionStream* raw_exception_stream = exception->exception();
189*9712c20fSFrederick Mayle   const MinidumpContext* context = exception->GetContext();
190*9712c20fSFrederick Mayle   // This should not evaluate to true, for the same reason mentioned above.
191*9712c20fSFrederick Mayle   if (!raw_exception_stream || !context) {
192*9712c20fSFrederick Mayle     BPLOG(INFO) << "No exception or architecture data.";
193*9712c20fSFrederick Mayle     return false;
194*9712c20fSFrederick Mayle   }
195*9712c20fSFrederick Mayle 
196*9712c20fSFrederick Mayle   DisassemblerObjdump disassembler(context->GetContextCPU(), memory_region,
197*9712c20fSFrederick Mayle                                    instruction_ptr);
198*9712c20fSFrederick Mayle   if (!disassembler.IsValid()) {
199*9712c20fSFrederick Mayle     BPLOG(INFO) << "Disassembling fault instruction failed.";
200*9712c20fSFrederick Mayle     return false;
201*9712c20fSFrederick Mayle   }
202*9712c20fSFrederick Mayle 
203*9712c20fSFrederick Mayle   // Check if the operation is a write to memory.
204*9712c20fSFrederick Mayle   // First, the instruction must one that can write to memory.
205*9712c20fSFrederick Mayle   auto instruction = disassembler.operation();
206*9712c20fSFrederick Mayle   if (!instruction.compare("mov") || !instruction.compare("inc") ||
207*9712c20fSFrederick Mayle       !instruction.compare("dec") || !instruction.compare("and") ||
208*9712c20fSFrederick Mayle       !instruction.compare("or") || !instruction.compare("xor") ||
209*9712c20fSFrederick Mayle       !instruction.compare("not") || !instruction.compare("neg") ||
210*9712c20fSFrederick Mayle       !instruction.compare("add") || !instruction.compare("sub") ||
211*9712c20fSFrederick Mayle       !instruction.compare("shl") || !instruction.compare("shr")) {
212*9712c20fSFrederick Mayle     uint64_t write_address = 0;
213*9712c20fSFrederick Mayle 
214*9712c20fSFrederick Mayle     // Check that the destination is a memory address. CalculateDestAddress will
215*9712c20fSFrederick Mayle     // return false if the destination is not a memory address.
216*9712c20fSFrederick Mayle     if (!disassembler.CalculateDestAddress(*context, write_address)) {
217*9712c20fSFrederick Mayle       return false;
218*9712c20fSFrederick Mayle     }
219*9712c20fSFrederick Mayle 
220*9712c20fSFrederick Mayle     // If the program crashed as a result of a write, the destination of
221*9712c20fSFrederick Mayle     // the write must have been an address that did not permit writing.
222*9712c20fSFrederick Mayle     // However, if the address is under 4k, due to program protections,
223*9712c20fSFrederick Mayle     // the crash does not suggest exploitability for writes with such a
224*9712c20fSFrederick Mayle     // low target address.
225*9712c20fSFrederick Mayle     return write_address > 4096;
226*9712c20fSFrederick Mayle   } else {
227*9712c20fSFrederick Mayle     return false;
228*9712c20fSFrederick Mayle   }
229*9712c20fSFrederick Mayle #endif  // __linux__
230*9712c20fSFrederick Mayle }
231*9712c20fSFrederick Mayle 
StackPointerOffStack(uint64_t stack_ptr)232*9712c20fSFrederick Mayle bool ExploitabilityLinux::StackPointerOffStack(uint64_t stack_ptr) {
233*9712c20fSFrederick Mayle   MinidumpLinuxMapsList* linux_maps_list = dump_->GetLinuxMapsList();
234*9712c20fSFrederick Mayle   // Inconclusive if there are no mappings available.
235*9712c20fSFrederick Mayle   if (!linux_maps_list) {
236*9712c20fSFrederick Mayle     return false;
237*9712c20fSFrederick Mayle   }
238*9712c20fSFrederick Mayle   const MinidumpLinuxMaps* linux_maps =
239*9712c20fSFrederick Mayle       linux_maps_list->GetLinuxMapsForAddress(stack_ptr);
240*9712c20fSFrederick Mayle   // Checks if the stack pointer maps to a valid mapping and if the mapping
241*9712c20fSFrederick Mayle   // is not the stack. If the mapping has no name, it is inconclusive whether
242*9712c20fSFrederick Mayle   // it is off the stack.
243*9712c20fSFrederick Mayle   return !linux_maps || (linux_maps->GetPathname().compare("") &&
244*9712c20fSFrederick Mayle                          linux_maps->GetPathname().compare(
245*9712c20fSFrederick Mayle                              0, strlen(kStackPrefix), kStackPrefix));
246*9712c20fSFrederick Mayle }
247*9712c20fSFrederick Mayle 
ExecutableStackOrHeap()248*9712c20fSFrederick Mayle bool ExploitabilityLinux::ExecutableStackOrHeap() {
249*9712c20fSFrederick Mayle   MinidumpLinuxMapsList* linux_maps_list = dump_->GetLinuxMapsList();
250*9712c20fSFrederick Mayle   if (linux_maps_list) {
251*9712c20fSFrederick Mayle     for (size_t i = 0; i < linux_maps_list->get_maps_count(); i++) {
252*9712c20fSFrederick Mayle       const MinidumpLinuxMaps* linux_maps =
253*9712c20fSFrederick Mayle           linux_maps_list->GetLinuxMapsAtIndex(i);
254*9712c20fSFrederick Mayle       // Check for executable stack or heap for each mapping.
255*9712c20fSFrederick Mayle       if (linux_maps && (!linux_maps->GetPathname().compare(
256*9712c20fSFrederick Mayle                              0, strlen(kStackPrefix), kStackPrefix) ||
257*9712c20fSFrederick Mayle                          !linux_maps->GetPathname().compare(
258*9712c20fSFrederick Mayle                              0, strlen(kHeapPrefix), kHeapPrefix)) &&
259*9712c20fSFrederick Mayle           linux_maps->IsExecutable()) {
260*9712c20fSFrederick Mayle         return true;
261*9712c20fSFrederick Mayle       }
262*9712c20fSFrederick Mayle     }
263*9712c20fSFrederick Mayle   }
264*9712c20fSFrederick Mayle   return false;
265*9712c20fSFrederick Mayle }
266*9712c20fSFrederick Mayle 
InstructionPointerInCode(uint64_t instruction_ptr)267*9712c20fSFrederick Mayle bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr) {
268*9712c20fSFrederick Mayle   // Get Linux memory mapping from /proc/self/maps. Checking whether the
269*9712c20fSFrederick Mayle   // region the instruction pointer is in has executable permission can tell
270*9712c20fSFrederick Mayle   // whether it is in a valid code region. If there is no mapping for the
271*9712c20fSFrederick Mayle   // instruction pointer, it is indicative that the instruction pointer is
272*9712c20fSFrederick Mayle   // not within a module, which implies that it is outside a valid area.
273*9712c20fSFrederick Mayle   MinidumpLinuxMapsList* linux_maps_list = dump_->GetLinuxMapsList();
274*9712c20fSFrederick Mayle   const MinidumpLinuxMaps* linux_maps =
275*9712c20fSFrederick Mayle       linux_maps_list ?
276*9712c20fSFrederick Mayle       linux_maps_list->GetLinuxMapsForAddress(instruction_ptr) : NULL;
277*9712c20fSFrederick Mayle   return linux_maps ? linux_maps->IsExecutable() : false;
278*9712c20fSFrederick Mayle }
279*9712c20fSFrederick Mayle 
BenignCrashTrigger(const MDRawExceptionStream * raw_exception_stream)280*9712c20fSFrederick Mayle bool ExploitabilityLinux::BenignCrashTrigger(
281*9712c20fSFrederick Mayle     const MDRawExceptionStream* raw_exception_stream) {
282*9712c20fSFrederick Mayle   // Check the cause of crash.
283*9712c20fSFrederick Mayle   // If the exception of the crash is a benign exception,
284*9712c20fSFrederick Mayle   // it is probably not exploitable.
285*9712c20fSFrederick Mayle   switch (raw_exception_stream->exception_record.exception_code) {
286*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGHUP:
287*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGINT:
288*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGQUIT:
289*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGTRAP:
290*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGABRT:
291*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGFPE:
292*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGKILL:
293*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGUSR1:
294*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGUSR2:
295*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGPIPE:
296*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGALRM:
297*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGTERM:
298*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGCHLD:
299*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGCONT:
300*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGSTOP:
301*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGTSTP:
302*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGTTIN:
303*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGTTOU:
304*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGURG:
305*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGXCPU:
306*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGXFSZ:
307*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGVTALRM:
308*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGPROF:
309*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGWINCH:
310*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGIO:
311*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGPWR:
312*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_SIGSYS:
313*9712c20fSFrederick Mayle     case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED:
314*9712c20fSFrederick Mayle       return true;
315*9712c20fSFrederick Mayle     default:
316*9712c20fSFrederick Mayle       return false;
317*9712c20fSFrederick Mayle   }
318*9712c20fSFrederick Mayle }
319*9712c20fSFrederick Mayle 
320*9712c20fSFrederick Mayle }  // namespace google_breakpad
321