aboutsummaryrefslogtreecommitdiff
path: root/src/processor/exploitability_linux.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/processor/exploitability_linux.cc')
-rw-r--r--src/processor/exploitability_linux.cc160
1 files changed, 10 insertions, 150 deletions
diff --git a/src/processor/exploitability_linux.cc b/src/processor/exploitability_linux.cc
index c1c291ce..3e99f89e 100644
--- a/src/processor/exploitability_linux.cc
+++ b/src/processor/exploitability_linux.cc
@@ -36,8 +36,6 @@
#include "processor/exploitability_linux.h"
-#include <elf.h>
-
#include "google_breakpad/common/minidump_exception_linux.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/process_state.h"
@@ -111,10 +109,6 @@ ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() {
return EXPLOITABILITY_ERR_PROCESSING;
}
- if (this->ArchitectureType() == UNSUPPORTED_ARCHITECTURE) {
- BPLOG(INFO) << "Unsupported architecture.";
- return EXPLOITABILITY_ERR_PROCESSING;
- }
// Getting the instruction pointer.
if (!context->GetInstructionPointer(&instruction_ptr)) {
BPLOG(INFO) << "Failed to retrieve instruction pointer.";
@@ -131,151 +125,17 @@ ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() {
return EXPLOITABILITY_INTERESTING;
}
-LinuxArchitectureType ExploitabilityLinux::ArchitectureType() {
- // GetContextCPU() should have already been successfully called before
- // calling this method. Thus there should be a raw exception stream for
- // the minidump.
- MinidumpException *exception = dump_->GetException();
- const DumpContext *dump_context =
- exception ?
- exception->GetContext() : NULL;
- if (dump_context == NULL) {
- BPLOG(INFO) << "No raw dump context.";
- return UNSUPPORTED_ARCHITECTURE;
- }
-
- // Check the architecture type.
- switch (dump_context->GetContextCPU()) {
- case MD_CONTEXT_ARM:
- case MD_CONTEXT_X86:
- return LINUX_32_BIT;
- case MD_CONTEXT_ARM64:
- case MD_CONTEXT_AMD64:
- return LINUX_64_BIT;
- default:
- // This should not happen. The four architectures above should be
- // the only Linux architectures.
- BPLOG(INFO) << "Unsupported architecture.";
- return UNSUPPORTED_ARCHITECTURE;
- }
-}
-
bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr) {
- // Get memory mapping. Most minidumps will not contain a memory
- // mapping, so processing will commonly resort to checking modules.
- MinidumpMemoryInfoList *mem_info_list = dump_->GetMemoryInfoList();
- const MinidumpMemoryInfo *mem_info =
- mem_info_list ?
- mem_info_list->GetMemoryInfoForAddress(instruction_ptr) : NULL;
-
- // Check if the memory mapping at the instruction pointer is executable.
- // If there is no memory mapping, processing will use modules as reference.
- if (mem_info != NULL) {
- return mem_info->IsExecutable();
- }
-
- // If the memory mapping retrieval fails, check the modules
- // to see if the instruction pointer is inside a module.
- MinidumpModuleList *minidump_module_list = dump_->GetModuleList();
- const MinidumpModule *minidump_module =
- minidump_module_list ?
- minidump_module_list->GetModuleForAddress(instruction_ptr) : NULL;
-
- // If the instruction pointer isn't in a module, return false.
- if (minidump_module == NULL) {
- return false;
- }
-
- // Get ELF header data from the instruction pointer's module.
- const uint64_t base_address = minidump_module->base_address();
- MinidumpMemoryList *memory_list = dump_->GetMemoryList();
- MinidumpMemoryRegion *memory_region =
- memory_list ?
- memory_list->GetMemoryRegionForAddress(base_address) : NULL;
-
- // The minidump does not have the correct memory region.
- // This returns true because even though there is no memory data available,
- // the evidence so far suggests that the instruction pointer is not at a
- // bad location.
- if (memory_region == NULL) {
- return true;
- }
-
- // Examine ELF headers. Depending on the architecture, the size of the
- // ELF headers can differ.
- LinuxArchitectureType architecture = this->ArchitectureType();
- if (architecture == LINUX_32_BIT) {
- // Check if the ELF header is within the memory region and if the
- // instruction pointer lies within the ELF header.
- if (memory_region->GetSize() < sizeof(Elf32_Ehdr) ||
- instruction_ptr < base_address + sizeof(Elf32_Ehdr)) {
- return false;
- }
- // Load 32-bit ELF header.
- Elf32_Ehdr header;
- this->LoadElfHeader(memory_region, base_address, &header);
- // Check if the program header table is within the memory region, and
- // validate that the program header entry size is correct.
- if (header.e_phentsize != sizeof(Elf32_Phdr) ||
- memory_region->GetSize() <
- header.e_phoff +
- ((uint64_t) header.e_phentsize * (uint64_t) header.e_phnum)) {
- return false;
- }
- // Load 32-bit Program Header Table.
- scoped_array<Elf32_Phdr> program_headers(new Elf32_Phdr[header.e_phnum]);
- this->LoadElfHeaderTable(memory_region,
- base_address + header.e_phoff,
- header.e_phnum,
- program_headers.get());
- // Find correct program header that corresponds to the instruction pointer.
- for (int i = 0; i < header.e_phnum; i++) {
- const Elf32_Phdr& program_header = program_headers[i];
- // Check if instruction pointer lies within this program header's region.
- if (instruction_ptr >= program_header.p_vaddr &&
- instruction_ptr < program_header.p_vaddr + program_header.p_memsz) {
- // Return whether this program header region is executable.
- return program_header.p_flags & PF_X;
- }
- }
- } else if (architecture == LINUX_64_BIT) {
- // Check if the ELF header is within the memory region and if the
- // instruction pointer lies within the ELF header.
- if (memory_region->GetSize() < sizeof(Elf64_Ehdr) ||
- instruction_ptr < base_address + sizeof(Elf64_Ehdr)) {
- return false;
- }
- // Load 64-bit ELF header.
- Elf64_Ehdr header;
- this->LoadElfHeader(memory_region, base_address, &header);
- // Check if the program header table is within the memory region, and
- // validate that the program header entry size is correct.
- if (header.e_phentsize != sizeof(Elf64_Phdr) ||
- memory_region->GetSize() <
- header.e_phoff +
- ((uint64_t) header.e_phentsize * (uint64_t) header.e_phnum)) {
- return false;
- }
- // Load 64-bit Program Header Table.
- scoped_array<Elf64_Phdr> program_headers(new Elf64_Phdr[header.e_phnum]);
- this->LoadElfHeaderTable(memory_region,
- base_address + header.e_phoff,
- header.e_phnum,
- program_headers.get());
- // Find correct program header that corresponds to the instruction pointer.
- for (int i = 0; i < header.e_phnum; i++) {
- const Elf64_Phdr& program_header = program_headers[i];
- // Check if instruction pointer lies within this program header's region.
- if (instruction_ptr >= program_header.p_vaddr &&
- instruction_ptr < program_header.p_vaddr + program_header.p_memsz) {
- // Return whether this program header region is executable.
- return program_header.p_flags & PF_X;
- }
- }
- }
-
- // The instruction pointer was not in an area identified by the ELF headers.
- return false;
+ // 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