OLD | NEW |
1 // Copyright (c) 2013 Google Inc. | 1 // Copyright (c) 2013 Google Inc. |
2 // All rights reserved. | 2 // All rights reserved. |
3 // | 3 // |
4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
6 // met: | 6 // met: |
7 // | 7 // |
8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
(...skipping 18 matching lines...) Expand all Loading... |
29 | 29 |
30 // exploitability_linux.cc: Linux specific exploitability engine. | 30 // exploitability_linux.cc: Linux specific exploitability engine. |
31 // | 31 // |
32 // Provides a guess at the exploitability of the crash for the Linux | 32 // Provides a guess at the exploitability of the crash for the Linux |
33 // platform given a minidump and process_state. | 33 // platform given a minidump and process_state. |
34 // | 34 // |
35 // Author: Matthew Riley | 35 // Author: Matthew Riley |
36 | 36 |
37 #include "processor/exploitability_linux.h" | 37 #include "processor/exploitability_linux.h" |
38 | 38 |
| 39 #include "google_breakpad/common/minidump_exception_linux.h" |
39 #include "google_breakpad/processor/process_state.h" | 40 #include "google_breakpad/processor/process_state.h" |
40 #include "google_breakpad/processor/call_stack.h" | 41 #include "google_breakpad/processor/call_stack.h" |
41 #include "google_breakpad/processor/stack_frame.h" | 42 #include "google_breakpad/processor/stack_frame.h" |
42 #include "processor/logging.h" | 43 #include "processor/logging.h" |
43 | 44 |
44 namespace { | 45 namespace { |
45 | 46 |
46 // This function in libc is called if the program was compiled with | 47 // This function in libc is called if the program was compiled with |
47 // -fstack-protector and a function's stack canary changes. | 48 // -fstack-protector and a function's stack canary changes. |
48 const char kStackCheckFailureFunction[] = "__stack_chk_fail"; | 49 const char kStackCheckFailureFunction[] = "__stack_chk_fail"; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 break; | 113 break; |
113 case MD_CONTEXT_ARM64: | 114 case MD_CONTEXT_ARM64: |
114 instruction_ptr = | 115 instruction_ptr = |
115 context->GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_PC]; | 116 context->GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_PC]; |
116 break; | 117 break; |
117 default: | 118 default: |
118 BPLOG(INFO) << "Unsupported architecture."; | 119 BPLOG(INFO) << "Unsupported architecture."; |
119 return EXPLOITABILITY_ERR_PROCESSING; | 120 return EXPLOITABILITY_ERR_PROCESSING; |
120 } | 121 } |
121 | 122 |
| 123 // Checking for the instruction pointer in a valid instruction region. |
122 if (!this->InstructionPointerInCode(instruction_ptr)) { | 124 if (!this->InstructionPointerInCode(instruction_ptr)) { |
123 return EXPLOITABILITY_HIGH; | 125 return EXPLOITABILITY_HIGH; |
124 } | 126 } |
125 | 127 |
126 return EXPLOITABILITY_NONE; | 128 const MDRawExceptionStream *raw_exception_stream = exception->exception(); |
| 129 if (raw_exception_stream == NULL) { |
| 130 BPLOG(INFO) << "No raw exception stream."; |
| 131 return EXPLOITABILITY_ERR_PROCESSING; |
| 132 } |
| 133 |
| 134 // Checking for benign exceptions that caused the crash. |
| 135 if (this->BenignCrashTrigger(raw_exception_stream)) { |
| 136 return EXPLOITABILITY_NONE; |
| 137 } |
| 138 |
| 139 return EXPLOITABILITY_INTERESTING; |
127 } | 140 } |
128 | 141 |
129 bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr) { | 142 bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr) { |
130 // Here we get memory mapping. Most minidumps will not contain a memory | 143 // Here we get memory mapping. Most minidumps will not contain a memory |
131 // mapping, so we will commonly resort to checking modules. | 144 // mapping, so we will commonly resort to checking modules. |
132 MinidumpMemoryInfoList *mem_info_list = dump_->GetMemoryInfoList(); | 145 MinidumpMemoryInfoList *mem_info_list = dump_->GetMemoryInfoList(); |
133 const MinidumpMemoryInfo *mem_info = | 146 const MinidumpMemoryInfo *mem_info = |
134 mem_info_list ? | 147 mem_info_list ? |
135 mem_info_list->GetMemoryInfoForAddress(instruction_ptr) : NULL; | 148 mem_info_list->GetMemoryInfoForAddress(instruction_ptr) : NULL; |
136 | 149 |
137 // Checking if the memory mapping at the instruction pointer is executable. | 150 // Checking if the memory mapping at the instruction pointer is executable. |
138 // If there is no memory mapping, we will use the modules as reference. | 151 // If there is no memory mapping, we will use the modules as reference. |
139 if (mem_info != NULL) { | 152 if (mem_info != NULL) { |
140 return mem_info->IsExecutable(); | 153 return mem_info->IsExecutable(); |
141 } | 154 } |
142 | 155 |
143 // If the memory mapping retrieval fails, we will check the modules | 156 // If the memory mapping retrieval fails, we will check the modules |
144 // to see if the instruction pointer is inside a module. | 157 // to see if the instruction pointer is inside a module. |
145 // TODO(liuandrew): Check if the instruction pointer lies in an executable | 158 // TODO(liuandrew): Check if the instruction pointer lies in an executable |
146 // region within the module. | 159 // region within the module. |
147 MinidumpModuleList *minidump_module_list = dump_->GetModuleList(); | 160 MinidumpModuleList *minidump_module_list = dump_->GetModuleList(); |
148 return !minidump_module_list || | 161 return !minidump_module_list || |
149 minidump_module_list->GetModuleForAddress(instruction_ptr); | 162 minidump_module_list->GetModuleForAddress(instruction_ptr); |
150 } | 163 } |
151 | 164 |
| 165 bool ExploitabilityLinux::BenignCrashTrigger(const MDRawExceptionStream |
| 166 *raw_exception_stream) { |
| 167 // Here we check the cause of crash. |
| 168 // If the exception of the crash is a benign exception, |
| 169 // it is probably not exploitable. |
| 170 switch (raw_exception_stream->exception_record.exception_code) { |
| 171 case MD_EXCEPTION_CODE_LIN_SIGHUP: |
| 172 case MD_EXCEPTION_CODE_LIN_SIGINT: |
| 173 case MD_EXCEPTION_CODE_LIN_SIGQUIT: |
| 174 case MD_EXCEPTION_CODE_LIN_SIGTRAP: |
| 175 case MD_EXCEPTION_CODE_LIN_SIGABRT: |
| 176 case MD_EXCEPTION_CODE_LIN_SIGFPE: |
| 177 case MD_EXCEPTION_CODE_LIN_SIGKILL: |
| 178 case MD_EXCEPTION_CODE_LIN_SIGUSR1: |
| 179 case MD_EXCEPTION_CODE_LIN_SIGUSR2: |
| 180 case MD_EXCEPTION_CODE_LIN_SIGPIPE: |
| 181 case MD_EXCEPTION_CODE_LIN_SIGALRM: |
| 182 case MD_EXCEPTION_CODE_LIN_SIGTERM: |
| 183 case MD_EXCEPTION_CODE_LIN_SIGCHLD: |
| 184 case MD_EXCEPTION_CODE_LIN_SIGCONT: |
| 185 case MD_EXCEPTION_CODE_LIN_SIGSTOP: |
| 186 case MD_EXCEPTION_CODE_LIN_SIGTSTP: |
| 187 case MD_EXCEPTION_CODE_LIN_SIGTTIN: |
| 188 case MD_EXCEPTION_CODE_LIN_SIGTTOU: |
| 189 case MD_EXCEPTION_CODE_LIN_SIGURG: |
| 190 case MD_EXCEPTION_CODE_LIN_SIGXCPU: |
| 191 case MD_EXCEPTION_CODE_LIN_SIGXFSZ: |
| 192 case MD_EXCEPTION_CODE_LIN_SIGVTALRM: |
| 193 case MD_EXCEPTION_CODE_LIN_SIGPROF: |
| 194 case MD_EXCEPTION_CODE_LIN_SIGWINCH: |
| 195 case MD_EXCEPTION_CODE_LIN_SIGIO: |
| 196 case MD_EXCEPTION_CODE_LIN_SIGPWR: |
| 197 case MD_EXCEPTION_CODE_LIN_SIGSYS: |
| 198 case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED: |
| 199 return true; |
| 200 break; |
| 201 default: |
| 202 return false; |
| 203 break; |
| 204 } |
| 205 } |
| 206 |
152 } // namespace google_breakpad | 207 } // namespace google_breakpad |
OLD | NEW |