aboutsummaryrefslogtreecommitdiff
path: root/externals/breakpad/src/processor/exploitability_linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'externals/breakpad/src/processor/exploitability_linux.cc')
-rw-r--r--externals/breakpad/src/processor/exploitability_linux.cc320
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