mirror of
https://git.suyu.dev/suyu/breakpad.git
synced 2026-03-08 00:06:27 +00:00
Add support for Linux memory mapping stream and remove ELF header usage
when checking exploitability rating. Linux minidumps do not support MD_MEMORY_INFO_LIST_STREAM, meaning the processor cannot retrieve its memory mappings. However, it has its own stream, MD_LINUX_MAPS, which contains memory mappings specific to Linux (it contains the contents of /proc/self/maps). This CL allows the minidump to gather information from the memory mappings for Linux minidumps. In addition, exploitability rating for Linux dumps now use memory mappings instead of checking the ELF headers of binaries. The basis for the change is that checking the ELF headers requires the minidumps to store the memory from the ELF headers, while the memory mapping data is already present, meaning the size of a minidump will be unchanged. As a result, of removing ELF header analysis, two unit tests have been removed. Arguably, the cases that those unit tests check do not merit a high exploitability rating and do not warrant a solid conclusion that was given earlier. R=ivanpe@chromium.org Review URL: https://codereview.chromium.org/1251593007 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1476 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
@@ -55,6 +55,7 @@
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "processor/range_map-inl.h"
|
||||
@@ -71,6 +72,7 @@ namespace google_breakpad {
|
||||
using std::istream;
|
||||
using std::ifstream;
|
||||
using std::numeric_limits;
|
||||
using std::stringstream;
|
||||
using std::vector;
|
||||
|
||||
// Returns true iff |context_size| matches exactly one of the sizes of the
|
||||
@@ -3972,6 +3974,142 @@ void MinidumpMemoryInfoList::Print() {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// MinidumpLinuxMaps
|
||||
//
|
||||
|
||||
MinidumpLinuxMaps::MinidumpLinuxMaps(Minidump *minidump)
|
||||
: MinidumpObject(minidump) {
|
||||
}
|
||||
|
||||
void MinidumpLinuxMaps::Print() {
|
||||
if (!valid_) {
|
||||
BPLOG(ERROR) << "MinidumpLinuxMaps cannot print invalid data";
|
||||
return;
|
||||
}
|
||||
std::cout << GetPathname() << std::endl;
|
||||
}
|
||||
|
||||
//
|
||||
// MinidumpLinuxMapsList
|
||||
//
|
||||
|
||||
MinidumpLinuxMapsList::MinidumpLinuxMapsList(Minidump *minidump)
|
||||
: MinidumpStream(minidump),
|
||||
maps_(NULL),
|
||||
maps_count_(0) {
|
||||
}
|
||||
|
||||
MinidumpLinuxMapsList::~MinidumpLinuxMapsList() {
|
||||
for (unsigned int i = 0; i < maps_->size(); i++) {
|
||||
delete (*maps_)[i];
|
||||
}
|
||||
delete maps_;
|
||||
}
|
||||
|
||||
const MinidumpLinuxMaps *MinidumpLinuxMapsList::GetLinuxMapsForAddress(
|
||||
uint64_t address) const {
|
||||
if (!valid_) {
|
||||
BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsForAddress";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Search every memory mapping.
|
||||
for (unsigned int index = 0; index < maps_count_; index++) {
|
||||
// Check if address is within bounds of the current memory region.
|
||||
if ((*maps_)[index]->GetBase() <= address &&
|
||||
(*maps_)[index]->GetBase() + (*maps_)[index]->GetSize() > address) {
|
||||
return (*maps_)[index];
|
||||
}
|
||||
}
|
||||
|
||||
// No mapping encloses the memory address.
|
||||
BPLOG(ERROR) << "MinidumpLinuxMapsList has no mapping at "
|
||||
<< HexString(address);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const MinidumpLinuxMaps *MinidumpLinuxMapsList::GetLinuxMapsAtIndex(
|
||||
unsigned int index) const {
|
||||
if (!valid_) {
|
||||
BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsAtIndex";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Index out of bounds.
|
||||
if (index >= maps_count_) {
|
||||
BPLOG(ERROR) << "MinidumpLinuxMapsList index of out range: "
|
||||
<< index
|
||||
<< "/"
|
||||
<< maps_count_;
|
||||
return NULL;
|
||||
}
|
||||
return (*maps_)[index];
|
||||
}
|
||||
|
||||
bool MinidumpLinuxMapsList::Read(uint32_t expected_size) {
|
||||
// Invalidate cached data.
|
||||
delete maps_;
|
||||
maps_ = NULL;
|
||||
maps_count_ = 0;
|
||||
|
||||
valid_ = false;
|
||||
|
||||
// Load and check expected stream length.
|
||||
uint32_t length = 0;
|
||||
if (!minidump_->SeekToStreamType(MD_LINUX_MAPS, &length)) {
|
||||
BPLOG(ERROR) << "MinidumpLinuxMapsList stream type not found";
|
||||
return false;
|
||||
}
|
||||
if (expected_size != length) {
|
||||
BPLOG(ERROR) << "MinidumpLinuxMapsList size mismatch: "
|
||||
<< expected_size
|
||||
<< " != "
|
||||
<< length;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a vector to read stream data. The vector needs to have
|
||||
// at least enough capacity to read all the data.
|
||||
vector<char> mapping_bytes(length);
|
||||
if (!minidump_->ReadBytes(&mapping_bytes[0], length)) {
|
||||
BPLOG(ERROR) << "MinidumpLinuxMapsList failed to read bytes";
|
||||
return false;
|
||||
}
|
||||
string map_string(mapping_bytes.begin(), mapping_bytes.end());
|
||||
vector<MappedMemoryRegion> all_regions;
|
||||
|
||||
// Parse string into mapping data.
|
||||
if (!ParseProcMaps(map_string, &all_regions)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scoped_ptr<MinidumpLinuxMappings> maps(new MinidumpLinuxMappings());
|
||||
|
||||
// Push mapping data into wrapper classes.
|
||||
for (size_t i = 0; i < all_regions.size(); i++) {
|
||||
scoped_ptr<MinidumpLinuxMaps> ele(new MinidumpLinuxMaps(minidump_));
|
||||
ele->region_ = all_regions[i];
|
||||
ele->valid_ = true;
|
||||
maps->push_back(ele.release());
|
||||
}
|
||||
|
||||
// Set instance variables.
|
||||
maps_ = maps.release();
|
||||
maps_count_ = maps_->size();
|
||||
valid_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MinidumpLinuxMapsList::Print() {
|
||||
if (!valid_) {
|
||||
BPLOG(ERROR) << "MinidumpLinuxMapsList cannot print valid data";
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < maps_->size(); i++) {
|
||||
(*maps_)[i]->Print();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Minidump
|
||||
@@ -4292,6 +4430,11 @@ MinidumpMemoryInfoList* Minidump::GetMemoryInfoList() {
|
||||
return GetStream(&memory_info_list);
|
||||
}
|
||||
|
||||
MinidumpLinuxMapsList *Minidump::GetLinuxMapsList() {
|
||||
MinidumpLinuxMapsList *linux_maps_list;
|
||||
return GetStream(&linux_maps_list);
|
||||
}
|
||||
|
||||
static const char* get_stream_name(uint32_t stream_type) {
|
||||
switch (stream_type) {
|
||||
case MD_UNUSED_STREAM:
|
||||
|
||||
Reference in New Issue
Block a user