diff options
Diffstat (limited to 'externals/breakpad/src/processor/exploitability_linux.cc')
| -rw-r--r-- | externals/breakpad/src/processor/exploitability_linux.cc | 320 |
1 files changed, 0 insertions, 320 deletions
diff --git a/externals/breakpad/src/processor/exploitability_linux.cc b/externals/breakpad/src/processor/exploitability_linux.cc deleted file mode 100644 index 76e78f45bc..0000000000 --- a/externals/breakpad/src/processor/exploitability_linux.cc +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright 2013 Google LLC -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google LLC nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// exploitability_linux.cc: Linux specific exploitability engine. -// -// Provides a guess at the exploitability of the crash for the Linux -// platform given a minidump and process_state. -// -// Author: Matthew Riley - -#ifdef HAVE_CONFIG_H -#include <config.h> // Must come first -#endif - -#include "processor/exploitability_linux.h" - -#include <string.h> - -#include "google_breakpad/common/minidump_exception_linux.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/process_state.h" -#include "google_breakpad/processor/stack_frame.h" -#ifdef __linux__ -#include "processor/disassembler_objdump.h" -#endif -#include "processor/logging.h" - -namespace { - -// Prefixes for memory mapping names. -constexpr char kHeapPrefix[] = "[heap"; -constexpr char kStackPrefix[] = "[stack"; - -// This function in libc is called if the program was compiled with -// -fstack-protector and a function's stack canary changes. -constexpr char kStackCheckFailureFunction[] = "__stack_chk_fail"; - -// This function in libc is called if the program was compiled with -// -D_FORTIFY_SOURCE=2, a function like strcpy() is called, and the runtime -// can determine that the call would overflow the target buffer. -constexpr char kBoundsCheckFailureFunction[] = "__chk_fail"; - -} // namespace - -namespace google_breakpad { - -ExploitabilityLinux::ExploitabilityLinux(Minidump* dump, - ProcessState* process_state) - : Exploitability(dump, process_state), - enable_objdump_(false) { } - -ExploitabilityLinux::ExploitabilityLinux(Minidump* dump, - ProcessState* process_state, - bool enable_objdump) - : Exploitability(dump, process_state), - enable_objdump_(enable_objdump) { } - - -ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() { - // Check the crashing thread for functions suggesting a buffer overflow or - // stack smash. - if (process_state_->requesting_thread() != -1) { - CallStack* crashing_thread = - process_state_->threads()->at(process_state_->requesting_thread()); - const vector<StackFrame*>& crashing_thread_frames = - *crashing_thread->frames(); - for (size_t i = 0; i < crashing_thread_frames.size(); ++i) { - if (crashing_thread_frames[i]->function_name == - kStackCheckFailureFunction) { - return EXPLOITABILITY_HIGH; - } - - if (crashing_thread_frames[i]->function_name == - kBoundsCheckFailureFunction) { - return EXPLOITABILITY_HIGH; - } - } - } - - // Getting exception data. (It should exist for all minidumps.) - MinidumpException* exception = dump_->GetException(); - if (exception == NULL) { - BPLOG(INFO) << "No exception record."; - return EXPLOITABILITY_ERR_PROCESSING; - } - const MDRawExceptionStream* raw_exception_stream = exception->exception(); - if (raw_exception_stream == NULL) { - BPLOG(INFO) << "No raw exception stream."; - return EXPLOITABILITY_ERR_PROCESSING; - } - - // Checking for benign exceptions that caused the crash. - if (this->BenignCrashTrigger(raw_exception_stream)) { - return EXPLOITABILITY_NONE; - } - - // Check if the instruction pointer is in a valid instruction region - // by finding if it maps to an executable part of memory. - uint64_t instruction_ptr = 0; - uint64_t stack_ptr = 0; - - const MinidumpContext* context = exception->GetContext(); - if (context == NULL) { - BPLOG(INFO) << "No exception context."; - return EXPLOITABILITY_ERR_PROCESSING; - } - - // Getting the instruction pointer. - if (!context->GetInstructionPointer(&instruction_ptr)) { - BPLOG(INFO) << "Failed to retrieve instruction pointer."; - return EXPLOITABILITY_ERR_PROCESSING; - } - - // Getting the stack pointer. - if (!context->GetStackPointer(&stack_ptr)) { - BPLOG(INFO) << "Failed to retrieve stack pointer."; - return EXPLOITABILITY_ERR_PROCESSING; - } - - // Checking for the instruction pointer in a valid instruction region, - // a misplaced stack pointer, and an executable stack or heap. - if (!this->InstructionPointerInCode(instruction_ptr) || - this->StackPointerOffStack(stack_ptr) || - this->ExecutableStackOrHeap()) { - return EXPLOITABILITY_HIGH; - } - - // Check for write to read only memory or invalid memory, shelling out - // to objdump is enabled. - if (enable_objdump_ && this->EndedOnIllegalWrite(instruction_ptr)) { - return EXPLOITABILITY_HIGH; - } - - // There was no strong evidence suggesting exploitability, but the minidump - // does not appear totally benign either. - return EXPLOITABILITY_INTERESTING; -} - -bool ExploitabilityLinux::EndedOnIllegalWrite(uint64_t instruction_ptr) { -#ifndef __linux__ - BPLOG(INFO) << "MinGW does not support fork and exec. Terminating method."; - return false; -#else - // Get memory region containing instruction pointer. - MinidumpMemoryList* memory_list = dump_->GetMemoryList(); - MinidumpMemoryRegion* memory_region = - memory_list ? - memory_list->GetMemoryRegionForAddress(instruction_ptr) : NULL; - if (!memory_region) { - BPLOG(INFO) << "No memory region around instruction pointer."; - return false; - } - - // Get exception data to find architecture. - string architecture = ""; - MinidumpException* exception = dump_->GetException(); - // This should never evaluate to true, since this should not be reachable - // without checking for exception data earlier. - if (!exception) { - BPLOG(INFO) << "No exception data."; - return false; - } - const MDRawExceptionStream* raw_exception_stream = exception->exception(); - const MinidumpContext* context = exception->GetContext(); - // This should not evaluate to true, for the same reason mentioned above. - if (!raw_exception_stream || !context) { - BPLOG(INFO) << "No exception or architecture data."; - return false; - } - - DisassemblerObjdump disassembler(context->GetContextCPU(), memory_region, - instruction_ptr); - if (!disassembler.IsValid()) { - BPLOG(INFO) << "Disassembling fault instruction failed."; - return false; - } - - // Check if the operation is a write to memory. - // First, the instruction must one that can write to memory. - auto instruction = disassembler.operation(); - if (!instruction.compare("mov") || !instruction.compare("inc") || - !instruction.compare("dec") || !instruction.compare("and") || - !instruction.compare("or") || !instruction.compare("xor") || - !instruction.compare("not") || !instruction.compare("neg") || - !instruction.compare("add") || !instruction.compare("sub") || - !instruction.compare("shl") || !instruction.compare("shr")) { - uint64_t write_address = 0; - - // Check that the destination is a memory address. CalculateDestAddress will - // return false if the destination is not a memory address. - if (!disassembler.CalculateDestAddress(*context, write_address)) { - return false; - } - - // If the program crashed as a result of a write, the destination of - // the write must have been an address that did not permit writing. - // However, if the address is under 4k, due to program protections, - // the crash does not suggest exploitability for writes with such a - // low target address. - return write_address > 4096; - } else { - return false; - } -#endif // __linux__ -} - -bool ExploitabilityLinux::StackPointerOffStack(uint64_t stack_ptr) { - MinidumpLinuxMapsList* linux_maps_list = dump_->GetLinuxMapsList(); - // Inconclusive if there are no mappings available. - if (!linux_maps_list) { - return false; - } - const MinidumpLinuxMaps* linux_maps = - linux_maps_list->GetLinuxMapsForAddress(stack_ptr); - // Checks if the stack pointer maps to a valid mapping and if the mapping - // is not the stack. If the mapping has no name, it is inconclusive whether - // it is off the stack. - return !linux_maps || (linux_maps->GetPathname().compare("") && - linux_maps->GetPathname().compare( - 0, strlen(kStackPrefix), kStackPrefix)); -} - -bool ExploitabilityLinux::ExecutableStackOrHeap() { - MinidumpLinuxMapsList* linux_maps_list = dump_->GetLinuxMapsList(); - if (linux_maps_list) { - for (size_t i = 0; i < linux_maps_list->get_maps_count(); i++) { - const MinidumpLinuxMaps* linux_maps = - linux_maps_list->GetLinuxMapsAtIndex(i); - // Check for executable stack or heap for each mapping. - if (linux_maps && (!linux_maps->GetPathname().compare( - 0, strlen(kStackPrefix), kStackPrefix) || - !linux_maps->GetPathname().compare( - 0, strlen(kHeapPrefix), kHeapPrefix)) && - linux_maps->IsExecutable()) { - return true; - } - } - } - return false; -} - -bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr) { - // Get Linux memory mapping from /proc/self/maps. Checking whether the - // region the instruction pointer is in has executable permission can tell - // whether it is in a valid code region. If there is no mapping for the - // instruction pointer, it is indicative that the instruction pointer is - // not within a module, which implies that it is outside a valid area. - MinidumpLinuxMapsList* linux_maps_list = dump_->GetLinuxMapsList(); - const MinidumpLinuxMaps* linux_maps = - linux_maps_list ? - linux_maps_list->GetLinuxMapsForAddress(instruction_ptr) : NULL; - return linux_maps ? linux_maps->IsExecutable() : false; -} - -bool ExploitabilityLinux::BenignCrashTrigger( - const MDRawExceptionStream* raw_exception_stream) { - // Check the cause of crash. - // If the exception of the crash is a benign exception, - // it is probably not exploitable. - switch (raw_exception_stream->exception_record.exception_code) { - case MD_EXCEPTION_CODE_LIN_SIGHUP: - case MD_EXCEPTION_CODE_LIN_SIGINT: - case MD_EXCEPTION_CODE_LIN_SIGQUIT: - case MD_EXCEPTION_CODE_LIN_SIGTRAP: - case MD_EXCEPTION_CODE_LIN_SIGABRT: - case MD_EXCEPTION_CODE_LIN_SIGFPE: - case MD_EXCEPTION_CODE_LIN_SIGKILL: - case MD_EXCEPTION_CODE_LIN_SIGUSR1: - case MD_EXCEPTION_CODE_LIN_SIGUSR2: - case MD_EXCEPTION_CODE_LIN_SIGPIPE: - case MD_EXCEPTION_CODE_LIN_SIGALRM: - case MD_EXCEPTION_CODE_LIN_SIGTERM: - case MD_EXCEPTION_CODE_LIN_SIGCHLD: - case MD_EXCEPTION_CODE_LIN_SIGCONT: - case MD_EXCEPTION_CODE_LIN_SIGSTOP: - case MD_EXCEPTION_CODE_LIN_SIGTSTP: - case MD_EXCEPTION_CODE_LIN_SIGTTIN: - case MD_EXCEPTION_CODE_LIN_SIGTTOU: - case MD_EXCEPTION_CODE_LIN_SIGURG: - case MD_EXCEPTION_CODE_LIN_SIGXCPU: - case MD_EXCEPTION_CODE_LIN_SIGXFSZ: - case MD_EXCEPTION_CODE_LIN_SIGVTALRM: - case MD_EXCEPTION_CODE_LIN_SIGPROF: - case MD_EXCEPTION_CODE_LIN_SIGWINCH: - case MD_EXCEPTION_CODE_LIN_SIGIO: - case MD_EXCEPTION_CODE_LIN_SIGPWR: - case MD_EXCEPTION_CODE_LIN_SIGSYS: - case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED: - return true; - default: - return false; - } -} - -} // namespace google_breakpad |
