Chromium Code Reviews| 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 21 matching lines...) Expand all Loading... | |
| 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/processor/process_state.h" | 39 #include "google_breakpad/processor/process_state.h" |
| 40 #include "google_breakpad/processor/call_stack.h" | 40 #include "google_breakpad/processor/call_stack.h" |
| 41 #include "google_breakpad/processor/stack_frame.h" | 41 #include "google_breakpad/processor/stack_frame.h" |
| 42 #include "processor/logging.h" | |
| 42 | 43 |
| 43 namespace { | 44 namespace { |
| 44 | 45 |
| 45 // This function in libc is called if the program was compiled with | 46 // This function in libc is called if the program was compiled with |
| 46 // -fstack-protector and a function's stack canary changes. | 47 // -fstack-protector and a function's stack canary changes. |
| 47 const char kStackCheckFailureFunction[] = "__stack_chk_fail"; | 48 const char kStackCheckFailureFunction[] = "__stack_chk_fail"; |
| 48 | 49 |
| 49 // This function in libc is called if the program was compiled with | 50 // This function in libc is called if the program was compiled with |
| 50 // -D_FORTIFY_SOURCE=2, a function like strcpy() is called, and the runtime | 51 // -D_FORTIFY_SOURCE=2, a function like strcpy() is called, and the runtime |
| 51 // can determine that the call would overflow the target buffer. | 52 // can determine that the call would overflow the target buffer. |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 73 return EXPLOITABILITY_HIGH; | 74 return EXPLOITABILITY_HIGH; |
| 74 } | 75 } |
| 75 | 76 |
| 76 if (crashing_thread_frames[i]->function_name == | 77 if (crashing_thread_frames[i]->function_name == |
| 77 kBoundsCheckFailureFunction) { | 78 kBoundsCheckFailureFunction) { |
| 78 return EXPLOITABILITY_HIGH; | 79 return EXPLOITABILITY_HIGH; |
| 79 } | 80 } |
| 80 } | 81 } |
| 81 } | 82 } |
| 82 | 83 |
| 84 // Check if the instruction pointer is in a valid instruction region | |
| 85 // by finding if it maps to an executable part of memory | |
| 86 uint64_t instruction_ptr = 0; | |
| 87 uint64_t stack_ptr = 0; | |
| 88 | |
| 89 // get exception data (should exist for all minidumps) | |
| 90 MinidumpException *exception = dump_->GetException(); | |
| 91 if (exception == NULL) { | |
| 92 BPLOG(INFO) << "No exception record."; | |
| 93 return EXPLOITABILITY_ERR_PROCESSING; | |
| 94 } | |
| 95 const MinidumpContext *context = exception->GetContext(); | |
| 96 if (context == NULL) { | |
| 97 BPLOG(INFO) << "No exception context."; | |
| 98 return EXPLOITABILITY_ERR_PROCESSING; | |
| 99 } | |
| 100 | |
| 101 // get instruction pointer based off architecture | |
| 102 uint32_t architecture = context->GetContextCPU(); | |
| 103 switch (architecture) { | |
| 104 case MD_CONTEXT_X86: | |
| 105 stack_ptr = context->GetContextX86()->esp; | |
| 106 instruction_ptr = context->GetContextX86()->eip; | |
| 107 break; | |
| 108 case MD_CONTEXT_AMD64: | |
| 109 stack_ptr = context->GetContextAMD64()->rsp; | |
| 110 instruction_ptr = context->GetContextAMD64()->rip; | |
| 111 break; | |
| 112 default: | |
|
ivanpe
2015/06/24 19:14:06
Please, add a TODO to handle ARM and arm64.
liuandrew
2015/06/24 20:59:36
Done.
| |
| 113 BPLOG(INFO) << "Unsupported architecture."; | |
| 114 return EXPLOITABILITY_ERR_PROCESSING; | |
| 115 } | |
| 116 | |
| 117 if (!this->InstructionPointerInCode(instruction_ptr, stack_ptr)) { | |
| 118 return EXPLOITABILITY_HIGH; | |
|
ivanpe
2015/06/24 19:14:06
Please, check with Cris Neckar or other security f
liuandrew
2015/06/24 20:59:36
Based off an automatic email response that I recei
| |
| 119 } | |
| 120 | |
| 83 return EXPLOITABILITY_NONE; | 121 return EXPLOITABILITY_NONE; |
| 84 } | 122 } |
| 85 | 123 |
| 124 bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr, | |
| 125 uint64_t stack_ptr) { | |
| 126 // get memory mapping | |
| 127 // most minidumps will not contain a memory mapping, so we will commonly | |
| 128 // resort to stack pointer approximation and checking modules | |
| 129 MinidumpMemoryInfoList *mem_info_list = dump_->GetMemoryInfoList(); | |
| 130 const MinidumpMemoryInfo *mem_info = | |
| 131 mem_info_list ? | |
| 132 mem_info_list->GetMemoryInfoForAddress(instruction_ptr) : NULL; | |
| 133 | |
| 134 // check if the memory mapping at the instruction pointer is executable | |
| 135 // if there is no memory mapping, we will use stack pointer approximation | |
| 136 // and the modules as reference | |
| 137 if (mem_info != NULL) { | |
| 138 return mem_info->IsExecutable(); | |
| 139 } | |
| 140 | |
| 141 // if the memory mapping retrieval fails, we will approximate | |
| 142 // the results by using the stack pointer, and we will check modules | |
| 143 // to see if the instruction pointer is inside a module | |
| 144 | |
| 145 // approximating if the instruction pointer is on the stack via | |
|
ivanpe
2015/06/24 19:14:06
As discussed offline, please remove this check, si
liuandrew
2015/06/24 20:59:36
Done.
| |
| 146 // stack pointer offset | |
| 147 const uint64_t offset = 0x2000; | |
| 148 if (stack_ptr + offset >= instruction_ptr && | |
| 149 stack_ptr - offset <= instruction_ptr) { | |
| 150 return false; | |
| 151 } | |
| 152 | |
| 153 // checking modules for instruction pointer inside any known module | |
| 154 // TODO(liuandrew) the entirety of a module is not necessarily executable | |
| 155 // check if the instruction pointer lies in an executable region | |
| 156 MinidumpModuleList *minidump_module_list = dump_->GetModuleList(); | |
| 157 return !minidump_module_list || | |
| 158 minidump_module_list->GetModuleForAddress(instruction_ptr); | |
| 159 } | |
| 160 | |
| 86 } // namespace google_breakpad | 161 } // namespace google_breakpad |
| OLD | NEW |