diff --git a/src/google_breakpad/processor/minidump.h b/src/google_breakpad/processor/minidump.h index ce1af851..2b5025e4 100644 --- a/src/google_breakpad/processor/minidump.h +++ b/src/google_breakpad/processor/minidump.h @@ -916,6 +916,9 @@ class MinidumpLinuxMapsList : public MinidumpStream { public: virtual ~MinidumpLinuxMapsList(); + // Get number of mappings. + unsigned int get_maps_count() const { return valid_ ? maps_count_ : 0; } + // Get mapping at the given memory address. The caller owns the pointer. const MinidumpLinuxMaps *GetLinuxMapsForAddress(uint64_t address) const; // Get mapping at the given index. The caller owns the pointer. diff --git a/src/processor/exploitability_linux.cc b/src/processor/exploitability_linux.cc index 0fae727c..46cad318 100644 --- a/src/processor/exploitability_linux.cc +++ b/src/processor/exploitability_linux.cc @@ -124,7 +124,8 @@ ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() { // Checking for the instruction pointer in a valid instruction region. if (!this->InstructionPointerInCode(instruction_ptr) || - this->StackPointerOffStack(stack_ptr)) { + this->StackPointerOffStack(stack_ptr) || + this->ExecutableStackOrHeap()) { return EXPLOITABILITY_HIGH; } @@ -149,6 +150,24 @@ bool ExploitabilityLinux::StackPointerOffStack(uint64_t stack_ptr) { linux_maps->GetPathname().compare("[stack]")); } +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("[stack]") || + !linux_maps->GetPathname().compare("[heap]")) && + 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 diff --git a/src/processor/exploitability_linux.h b/src/processor/exploitability_linux.h index 9d9fa695..857185b4 100644 --- a/src/processor/exploitability_linux.h +++ b/src/processor/exploitability_linux.h @@ -51,17 +51,21 @@ class ExploitabilityLinux : public Exploitability { virtual ExploitabilityRating CheckPlatformExploitability(); private: - // This method takes the address of the instruction pointer and returns + // Takes the address of the instruction pointer and returns // whether the instruction pointer lies in a valid instruction region. bool InstructionPointerInCode(uint64_t instruction_ptr); - // This method checks the exception that triggered the creation of the + // 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); + + // Checks if the stack or heap are marked executable according + // to the memory mappings. + bool ExecutableStackOrHeap(); }; } // namespace google_breakpad diff --git a/src/processor/exploitability_unittest.cc b/src/processor/exploitability_unittest.cc index db668d80..db7f1cb0 100644 --- a/src/processor/exploitability_unittest.cc +++ b/src/processor/exploitability_unittest.cc @@ -131,6 +131,10 @@ TEST(ExploitabilityTest, TestLinuxEngine) { ExploitabilityFor("linux_stack_pointer_in_stack.dmp")); ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, ExploitabilityFor("linux_stack_pointer_in_module.dmp")); + ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, + ExploitabilityFor("linux_executable_stack.dmp")); + ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, + ExploitabilityFor("linux_executable_heap.dmp")); } } diff --git a/src/processor/testdata/linux_executable_heap.dmp b/src/processor/testdata/linux_executable_heap.dmp new file mode 100644 index 00000000..f8c807fa Binary files /dev/null and b/src/processor/testdata/linux_executable_heap.dmp differ diff --git a/src/processor/testdata/linux_executable_stack.dmp b/src/processor/testdata/linux_executable_stack.dmp new file mode 100644 index 00000000..c424cb20 Binary files /dev/null and b/src/processor/testdata/linux_executable_stack.dmp differ