diff --git a/src/processor/exploitability_linux.cc b/src/processor/exploitability_linux.cc index 3e99f89e..0fae727c 100644 --- a/src/processor/exploitability_linux.cc +++ b/src/processor/exploitability_linux.cc @@ -102,6 +102,7 @@ ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() { // 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) { @@ -115,8 +116,15 @@ ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() { 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. - if (!this->InstructionPointerInCode(instruction_ptr)) { + if (!this->InstructionPointerInCode(instruction_ptr) || + this->StackPointerOffStack(stack_ptr)) { return EXPLOITABILITY_HIGH; } @@ -125,6 +133,22 @@ ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() { return EXPLOITABILITY_INTERESTING; } +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("[stack]")); +} + 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 diff --git a/src/processor/exploitability_linux.h b/src/processor/exploitability_linux.h index 6332b074..9d9fa695 100644 --- a/src/processor/exploitability_linux.h +++ b/src/processor/exploitability_linux.h @@ -58,6 +58,10 @@ class ExploitabilityLinux : public Exploitability { // This method checks the exception that triggered the creation of the // minidump and reports whether the exception suggests no exploitability. bool BenignCrashTrigger(const MDRawExceptionStream *raw_exception_stream); + + // Checks if the stack pointer points to a memory mapping that is not + // labelled as the stack. + bool StackPointerOffStack(uint64_t stack_ptr); }; } // namespace google_breakpad diff --git a/src/processor/exploitability_unittest.cc b/src/processor/exploitability_unittest.cc index 8a42baa0..db668d80 100644 --- a/src/processor/exploitability_unittest.cc +++ b/src/processor/exploitability_unittest.cc @@ -127,6 +127,10 @@ TEST(ExploitabilityTest, TestLinuxEngine) { ExploitabilityFor("linux_inside_module_exe_region1.dmp")); ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING, ExploitabilityFor("linux_inside_module_exe_region2.dmp")); + ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING, + ExploitabilityFor("linux_stack_pointer_in_stack.dmp")); + ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, + ExploitabilityFor("linux_stack_pointer_in_module.dmp")); } } diff --git a/src/processor/testdata/linux_stack_pointer_in_module.dmp b/src/processor/testdata/linux_stack_pointer_in_module.dmp new file mode 100644 index 00000000..92b6c21a Binary files /dev/null and b/src/processor/testdata/linux_stack_pointer_in_module.dmp differ diff --git a/src/processor/testdata/linux_stack_pointer_in_stack.dmp b/src/processor/testdata/linux_stack_pointer_in_stack.dmp new file mode 100644 index 00000000..f70b881f Binary files /dev/null and b/src/processor/testdata/linux_stack_pointer_in_stack.dmp differ