Commit 6f650c50 authored by Joshua Peraza's avatar Joshua Peraza Committed by Commit Bot

Update Crashpad to 688dcfa22ee906f83d49b905b69c7c53347c92d9

9ae453628f50 android: handle RELRO sharing by the Chromium linker
688dcfa22ee9 android: handle modules loaded from zipfiles

Change-Id: Ib295fb1e0f0571c38f9bf5603eda349b9f8e15da
Reviewed-on: https://chromium-review.googlesource.com/1236467Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Commit-Queue: Joshua Peraza <jperaza@chromium.org>
Cr-Commit-Position: refs/heads/master@{#592924}
parent db6b7b1c
...@@ -2,7 +2,7 @@ Name: Crashpad ...@@ -2,7 +2,7 @@ Name: Crashpad
Short Name: crashpad Short Name: crashpad
URL: https://crashpad.chromium.org/ URL: https://crashpad.chromium.org/
Version: unknown Version: unknown
Revision: 8595f4b4231d82284c877b54463952a68d209fd4 Revision: 688dcfa22ee906f83d49b905b69c7c53347c92d9
License: Apache 2.0 License: Apache 2.0
License File: crashpad/LICENSE License File: crashpad/LICENSE
Security Critical: yes Security Critical: yes
......
...@@ -467,6 +467,20 @@ uint16_t ElfImageReader::FileType() const { ...@@ -467,6 +467,20 @@ uint16_t ElfImageReader::FileType() const {
return memory_.Is64Bit() ? header_64_.e_type : header_32_.e_type; return memory_.Is64Bit() ? header_64_.e_type : header_32_.e_type;
} }
bool ElfImageReader::SoName(std::string* name) {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
if (!InitializeDynamicArray()) {
return false;
}
VMSize offset;
if (!dynamic_array_->GetValue(DT_SONAME, true, &offset)) {
return false;
}
return ReadDynamicStringTableAtOffset(offset, name);
}
bool ElfImageReader::GetDynamicSymbol(const std::string& name, bool ElfImageReader::GetDynamicSymbol(const std::string& name,
VMAddress* address, VMAddress* address,
VMSize* size) { VMSize* size) {
......
...@@ -149,6 +149,13 @@ class ElfImageReader { ...@@ -149,6 +149,13 @@ class ElfImageReader {
//! The load bias is the actual load address minus the preferred load address. //! The load bias is the actual load address minus the preferred load address.
VMOffset GetLoadBias() const { return load_bias_; } VMOffset GetLoadBias() const { return load_bias_; }
//! \brief Determines the name of this object using `DT_SONAME`, if present.
//!
//! \param[out] name The name of this object, only valid if this method
//! returns `true`.
//! \return `true` if a name was found for this object.
bool SoName(std::string* name);
//! \brief Reads information from the dynamic symbol table about the symbol //! \brief Reads information from the dynamic symbol table about the symbol
//! identified by \a name. //! identified by \a name.
//! //!
......
...@@ -433,7 +433,12 @@ void ProcessReaderLinux::InitializeModules() { ...@@ -433,7 +433,12 @@ void ProcessReaderLinux::InitializeModules() {
} }
Module module = {}; Module module = {};
module.name = !entry.name.empty() ? entry.name : module_mapping->name; std::string soname;
if (elf_reader->SoName(&soname) && !soname.empty()) {
module.name = soname;
} else {
module.name = !entry.name.empty() ? entry.name : module_mapping->name;
}
module.elf_reader = elf_reader.get(); module.elf_reader = elf_reader.get();
module.type = loader_base && elf_reader->Address() == loader_base module.type = loader_base && elf_reader->Address() == loader_base
? ModuleSnapshot::kModuleTypeDynamicLoader ? ModuleSnapshot::kModuleTypeDynamicLoader
......
...@@ -316,10 +316,46 @@ std::vector<const MemoryMap::Mapping*> MemoryMap::FindFilePossibleMmapStarts( ...@@ -316,10 +316,46 @@ std::vector<const MemoryMap::Mapping*> MemoryMap::FindFilePossibleMmapStarts(
return std::vector<const Mapping*>(); return std::vector<const Mapping*>();
} }
#if defined(OS_ANDROID)
// The Android Chromium linker uses ashmem to share RELRO segments between
// processes. The original RELRO segment has been unmapped and replaced with a
// mapping named "/dev/ashmem/RELRO:<libname>" where <libname> is the base
// library name (e.g. libchrome.so) sans any preceding path that may be
// present in other mappings for the library.
// https://crashpad.chromium.org/bug/253
static constexpr char kRelro[] = "/dev/ashmem/RELRO:";
if (mapping.name.compare(0, strlen(kRelro), kRelro, 0, strlen(kRelro)) == 0) {
// The kernel appends "(deleted)" to ashmem mappings because there isn't
// any corresponding file on the filesystem.
static constexpr char kDeleted[] = " (deleted)";
size_t libname_end = mapping.name.rfind(kDeleted);
DCHECK_NE(libname_end, std::string::npos);
if (libname_end == std::string::npos) {
libname_end = mapping.name.size();
}
std::string libname =
mapping.name.substr(strlen(kRelro), libname_end - strlen(kRelro));
for (const auto& candidate : mappings_) {
if (candidate.name.rfind(libname) != std::string::npos) {
possible_starts.push_back(&candidate);
}
if (mapping.Equals(candidate)) {
return possible_starts;
}
}
}
#endif // OS_ANDROID
for (const auto& candidate : mappings_) { for (const auto& candidate : mappings_) {
if (candidate.device == mapping.device && if (candidate.device == mapping.device &&
candidate.inode == mapping.inode && candidate.inode == mapping.inode
candidate.offset == 0) { #if !defined(OS_ANDROID)
// Libraries on Android may be mapped from zipfiles (APKs), in which
// case the offset is not 0.
&& candidate.offset == 0
#endif // !defined(OS_ANDROID)
) {
possible_starts.push_back(&candidate); possible_starts.push_back(&candidate);
} }
if (mapping.Equals(candidate)) { if (mapping.Equals(candidate)) {
......
...@@ -76,14 +76,19 @@ class MemoryMap { ...@@ -76,14 +76,19 @@ class MemoryMap {
//! it was obtained from. //! it was obtained from.
const Mapping* FindMappingWithName(const std::string& name) const; const Mapping* FindMappingWithName(const std::string& name) const;
//! \brief Find Mappings that share a Mapping's file, mapped from offset 0. //! \brief Find possible initial mappings of files mapped over several
//! segments.
//! //!
//! Executables and libaries are typically loaded into several mappings with //! Executables and libaries are typically loaded into several mappings with
//! varying permissions for different segments. Portions of an ELF file may //! varying permissions for different segments. Portions of an ELF file may
//! be mapped multiple times as part of loading the file, for example, when //! be mapped multiple times as part of loading the file, for example, when
//! initializing GNU_RELRO segments. This method searches for mappings at or //! initializing GNU_RELRO segments.
//! below \a mapping in memory that are mapped from the same file as \a //!
//! mapping from offset 0. //! This method searches for mappings at or below \a mapping in memory that
//! are mapped from the same file as \a mapping from offset 0.
//!
//! On Android, ELF modules may be loaded from within a zipfile, so this
//! method may return mappings whose offset is not 0.
//! //!
//! This method is intended to help identify the possible base address for //! This method is intended to help identify the possible base address for
//! loaded modules, but it is the caller's responsibility to determine which //! loaded modules, but it is the caller's responsibility to determine which
......
...@@ -384,8 +384,12 @@ void ExpectFindFilePossibleMmapStarts(LinuxVMAddress mapping_start, ...@@ -384,8 +384,12 @@ void ExpectFindFilePossibleMmapStarts(LinuxVMAddress mapping_start,
EXPECT_EQ(mappings[0], mapping2); EXPECT_EQ(mappings[0], mapping2);
mappings = map.FindFilePossibleMmapStarts(*mapping3); mappings = map.FindFilePossibleMmapStarts(*mapping3);
#if defined(OS_ANDROID)
EXPECT_EQ(mappings.size(), 2u);
#else
ASSERT_EQ(mappings.size(), 1u); ASSERT_EQ(mappings.size(), 1u);
EXPECT_EQ(mappings[0], mapping1); EXPECT_EQ(mappings[0], mapping1);
#endif
} }
TEST(MemoryMap, FindFilePossibleMmapStarts) { TEST(MemoryMap, FindFilePossibleMmapStarts) {
...@@ -430,6 +434,16 @@ TEST(MemoryMap, FindFilePossibleMmapStarts) { ...@@ -430,6 +434,16 @@ TEST(MemoryMap, FindFilePossibleMmapStarts) {
std::vector<const MemoryMap::Mapping*> mappings; std::vector<const MemoryMap::Mapping*> mappings;
#if defined(OS_ANDROID)
mappings = map.FindFilePossibleMmapStarts(*mapping1);
EXPECT_EQ(mappings.size(), 1u);
mappings = map.FindFilePossibleMmapStarts(*mapping2);
EXPECT_EQ(mappings.size(), 2u);
mappings = map.FindFilePossibleMmapStarts(*mapping3);
EXPECT_EQ(mappings.size(), 3u);
#else
mappings = map.FindFilePossibleMmapStarts(*mapping1); mappings = map.FindFilePossibleMmapStarts(*mapping1);
ASSERT_EQ(mappings.size(), 1u); ASSERT_EQ(mappings.size(), 1u);
EXPECT_EQ(mappings[0], mapping1); EXPECT_EQ(mappings[0], mapping1);
...@@ -441,6 +455,7 @@ TEST(MemoryMap, FindFilePossibleMmapStarts) { ...@@ -441,6 +455,7 @@ TEST(MemoryMap, FindFilePossibleMmapStarts) {
mappings = map.FindFilePossibleMmapStarts(*mapping3); mappings = map.FindFilePossibleMmapStarts(*mapping3);
ASSERT_EQ(mappings.size(), 1u); ASSERT_EQ(mappings.size(), 1u);
EXPECT_EQ(mappings[0], mapping1); EXPECT_EQ(mappings[0], mapping1);
#endif
#if defined(ARCH_CPU_64_BITS) #if defined(ARCH_CPU_64_BITS)
constexpr bool is_64_bit = true; constexpr bool is_64_bit = true;
...@@ -562,27 +577,47 @@ TEST(MemoryMap, FindFilePossibleMmapStarts_MultipleStarts) { ...@@ -562,27 +577,47 @@ TEST(MemoryMap, FindFilePossibleMmapStarts_MultipleStarts) {
auto mapping = map.FindMapping(file_mapping0.addr_as<VMAddress>()); auto mapping = map.FindMapping(file_mapping0.addr_as<VMAddress>());
ASSERT_TRUE(mapping); ASSERT_TRUE(mapping);
auto possible_starts = map.FindFilePossibleMmapStarts(*mapping); auto possible_starts = map.FindFilePossibleMmapStarts(*mapping);
#if defined(OS_ANDROID)
EXPECT_EQ(possible_starts.size(), 1u);
#else
EXPECT_EQ(possible_starts.size(), 0u); EXPECT_EQ(possible_starts.size(), 0u);
#endif
mapping = map.FindMapping(file_mapping1.addr_as<VMAddress>()); mapping = map.FindMapping(file_mapping1.addr_as<VMAddress>());
ASSERT_TRUE(mapping); ASSERT_TRUE(mapping);
possible_starts = map.FindFilePossibleMmapStarts(*mapping); possible_starts = map.FindFilePossibleMmapStarts(*mapping);
#if defined(OS_ANDROID)
EXPECT_EQ(possible_starts.size(), 2u);
#else
EXPECT_EQ(possible_starts.size(), 1u); EXPECT_EQ(possible_starts.size(), 1u);
#endif
mapping = map.FindMapping(file_mapping2.addr_as<VMAddress>()); mapping = map.FindMapping(file_mapping2.addr_as<VMAddress>());
ASSERT_TRUE(mapping); ASSERT_TRUE(mapping);
possible_starts = map.FindFilePossibleMmapStarts(*mapping); possible_starts = map.FindFilePossibleMmapStarts(*mapping);
#if defined(OS_ANDROID)
EXPECT_EQ(possible_starts.size(), 3u);
#else
EXPECT_EQ(possible_starts.size(), 2u); EXPECT_EQ(possible_starts.size(), 2u);
#endif
mapping = map.FindMapping(file_mapping3.addr_as<VMAddress>()); mapping = map.FindMapping(file_mapping3.addr_as<VMAddress>());
ASSERT_TRUE(mapping); ASSERT_TRUE(mapping);
possible_starts = map.FindFilePossibleMmapStarts(*mapping); possible_starts = map.FindFilePossibleMmapStarts(*mapping);
#if defined(OS_ANDROID)
EXPECT_EQ(possible_starts.size(), 4u);
#else
EXPECT_EQ(possible_starts.size(), 3u); EXPECT_EQ(possible_starts.size(), 3u);
#endif
mapping = map.FindMapping(file_mapping4.addr_as<VMAddress>()); mapping = map.FindMapping(file_mapping4.addr_as<VMAddress>());
ASSERT_TRUE(mapping); ASSERT_TRUE(mapping);
possible_starts = map.FindFilePossibleMmapStarts(*mapping); possible_starts = map.FindFilePossibleMmapStarts(*mapping);
#if defined(OS_ANDROID)
EXPECT_EQ(possible_starts.size(), 5u);
#else
EXPECT_EQ(possible_starts.size(), 4u); EXPECT_EQ(possible_starts.size(), 4u);
#endif
} }
} // namespace } // namespace
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment