mirror of
https://git.suyu.dev/suyu/breakpad.git
synced 2025-12-27 17:55:29 +01: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:
parent
4959c18e98
commit
2997f45907
12 changed files with 885 additions and 214 deletions
103
src/processor/proc_maps_linux.cc
Normal file
103
src/processor/proc_maps_linux.cc
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "google_breakpad/processor/proc_maps_linux.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(OS_LINUX) || defined(OS_ANDROID)
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#include "processor/logging.h"
|
||||
|
||||
#if defined(OS_ANDROID) && !defined(__LP64__)
|
||||
// In 32-bit mode, Bionic's inttypes.h defines PRI/SCNxPTR as an
|
||||
// unsigned long int, which is incompatible with Bionic's stdint.h
|
||||
// defining uintptr_t as an unsigned int:
|
||||
// https://code.google.com/p/android/issues/detail?id=57218
|
||||
#undef SCNxPTR
|
||||
#define SCNxPTR "x"
|
||||
#endif
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
bool ParseProcMaps(const std::string& input,
|
||||
std::vector<MappedMemoryRegion>* regions_out) {
|
||||
std::vector<MappedMemoryRegion> regions;
|
||||
|
||||
// This isn't async safe nor terribly efficient, but it doesn't need to be at
|
||||
// this point in time.
|
||||
|
||||
// Split the string by newlines.
|
||||
std::vector<std::string> lines;
|
||||
std::string line = "";
|
||||
for (size_t i = 0; i < input.size(); i++) {
|
||||
if (input[i] != '\n' && input[i] != '\r') {
|
||||
line.push_back(input[i]);
|
||||
} else if (line.size() > 0) {
|
||||
lines.push_back(line);
|
||||
line.clear();
|
||||
}
|
||||
}
|
||||
if (line.size() > 0) {
|
||||
BPLOG(ERROR) << "Input doesn't end in newline";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < lines.size(); ++i) {
|
||||
MappedMemoryRegion region;
|
||||
const char* line = lines[i].c_str();
|
||||
char permissions[5] = {'\0'}; // Ensure NUL-terminated string.
|
||||
int path_index = 0;
|
||||
|
||||
// Sample format from man 5 proc:
|
||||
//
|
||||
// address perms offset dev inode pathname
|
||||
// 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm
|
||||
//
|
||||
// The final %n term captures the offset in the input string, which is used
|
||||
// to determine the path name. It *does not* increment the return value.
|
||||
// Refer to man 3 sscanf for details.
|
||||
if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR " %4c %lx %hhx:%hhx %ld %n",
|
||||
®ion.start, ®ion.end, permissions, ®ion.offset,
|
||||
®ion.major_device, ®ion.minor_device, ®ion.inode,
|
||||
&path_index) < 7) {
|
||||
BPLOG(ERROR) << "sscanf failed for line: " << line;
|
||||
return false;
|
||||
}
|
||||
|
||||
region.permissions = 0;
|
||||
|
||||
if (permissions[0] == 'r')
|
||||
region.permissions |= MappedMemoryRegion::READ;
|
||||
else if (permissions[0] != '-')
|
||||
return false;
|
||||
|
||||
if (permissions[1] == 'w')
|
||||
region.permissions |= MappedMemoryRegion::WRITE;
|
||||
else if (permissions[1] != '-')
|
||||
return false;
|
||||
|
||||
if (permissions[2] == 'x')
|
||||
region.permissions |= MappedMemoryRegion::EXECUTE;
|
||||
else if (permissions[2] != '-')
|
||||
return false;
|
||||
|
||||
if (permissions[3] == 'p')
|
||||
region.permissions |= MappedMemoryRegion::PRIVATE;
|
||||
else if (permissions[3] != 's' && permissions[3] != 'S') // Shared memory.
|
||||
return false;
|
||||
|
||||
// Pushing then assigning saves us a string copy.
|
||||
regions.push_back(region);
|
||||
regions.back().path.assign(line + path_index);
|
||||
}
|
||||
|
||||
regions_out->swap(regions);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
Loading…
Add table
Add a link
Reference in a new issue