mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 15:32:10 +08:00
elf: adjust small DT_STRTAB addresses by load bias
Change-Id: I7ffbd2be0800aedad8b5c4b6982379e5485f1bc8 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2229114 Commit-Queue: Joshua Peraza <jperaza@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
parent
86c28287d2
commit
294d233ca0
@ -589,6 +589,14 @@ bool ElfImageReader::ReadDynamicStringTableAtOffset(VMSize offset,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GNU ld.so doesn't adjust the vdso's dynamic array entries by the load bias.
|
||||||
|
// If the address is too small to point into the loaded module range and is
|
||||||
|
// small enough to be an offset from the base of the module, adjust it now.
|
||||||
|
if (string_table_address < memory_.Base() &&
|
||||||
|
string_table_address < memory_.Size()) {
|
||||||
|
string_table_address += GetLoadBias();
|
||||||
|
}
|
||||||
|
|
||||||
if (!memory_.ReadCStringSizeLimited(
|
if (!memory_.ReadCStringSizeLimited(
|
||||||
string_table_address + offset, string_table_size - offset, string)) {
|
string_table_address + offset, string_table_size - offset, string)) {
|
||||||
LOG(ERROR) << "missing nul-terminator";
|
LOG(ERROR) << "missing nul-terminator";
|
||||||
|
@ -535,7 +535,8 @@ void ExpectModulesFromSelf(
|
|||||||
#endif // !OS_ANDROID || !ARCH_CPU_ARMEL || __ANDROID_API__ >= 21
|
#endif // !OS_ANDROID || !ARCH_CPU_ARMEL || __ANDROID_API__ >= 21
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteTestModule(const base::FilePath& module_path) {
|
bool WriteTestModule(const base::FilePath& module_path,
|
||||||
|
const std::string& soname) {
|
||||||
#if defined(ARCH_CPU_64_BITS)
|
#if defined(ARCH_CPU_64_BITS)
|
||||||
using Ehdr = Elf64_Ehdr;
|
using Ehdr = Elf64_Ehdr;
|
||||||
using Phdr = Elf64_Phdr;
|
using Phdr = Elf64_Phdr;
|
||||||
@ -565,6 +566,7 @@ bool WriteTestModule(const base::FilePath& module_path) {
|
|||||||
Dyn symtab;
|
Dyn symtab;
|
||||||
Dyn strsz;
|
Dyn strsz;
|
||||||
Dyn syment;
|
Dyn syment;
|
||||||
|
Dyn soname;
|
||||||
Dyn null;
|
Dyn null;
|
||||||
} dynamic_array;
|
} dynamic_array;
|
||||||
struct {
|
struct {
|
||||||
@ -573,8 +575,7 @@ bool WriteTestModule(const base::FilePath& module_path) {
|
|||||||
Elf32_Word bucket;
|
Elf32_Word bucket;
|
||||||
Elf32_Word chain;
|
Elf32_Word chain;
|
||||||
} hash_table;
|
} hash_table;
|
||||||
struct {
|
char string_table[32];
|
||||||
} string_table;
|
|
||||||
struct {
|
struct {
|
||||||
} section_header_string_table;
|
} section_header_string_table;
|
||||||
struct {
|
struct {
|
||||||
@ -671,6 +672,9 @@ bool WriteTestModule(const base::FilePath& module_path) {
|
|||||||
module.dynamic_array.strsz.d_un.d_val = sizeof(module.string_table);
|
module.dynamic_array.strsz.d_un.d_val = sizeof(module.string_table);
|
||||||
module.dynamic_array.syment.d_tag = DT_SYMENT;
|
module.dynamic_array.syment.d_tag = DT_SYMENT;
|
||||||
module.dynamic_array.syment.d_un.d_val = sizeof(Sym);
|
module.dynamic_array.syment.d_un.d_val = sizeof(Sym);
|
||||||
|
constexpr size_t kSonameOffset = 1;
|
||||||
|
module.dynamic_array.soname.d_tag = DT_SONAME;
|
||||||
|
module.dynamic_array.soname.d_un.d_val = kSonameOffset;
|
||||||
|
|
||||||
module.dynamic_array.null.d_tag = DT_NULL;
|
module.dynamic_array.null.d_tag = DT_NULL;
|
||||||
|
|
||||||
@ -679,6 +683,10 @@ bool WriteTestModule(const base::FilePath& module_path) {
|
|||||||
module.hash_table.bucket = 0;
|
module.hash_table.bucket = 0;
|
||||||
module.hash_table.chain = 0;
|
module.hash_table.chain = 0;
|
||||||
|
|
||||||
|
CHECK_GE(sizeof(module.string_table), soname.size() + 2);
|
||||||
|
module.string_table[0] = '\0';
|
||||||
|
memcpy(&module.string_table[kSonameOffset], soname.c_str(), soname.size());
|
||||||
|
|
||||||
module.shdr_table.null.sh_type = SHT_NULL;
|
module.shdr_table.null.sh_type = SHT_NULL;
|
||||||
|
|
||||||
module.shdr_table.dynamic.sh_name = 0;
|
module.shdr_table.dynamic.sh_name = 0;
|
||||||
@ -716,11 +724,12 @@ bool WriteTestModule(const base::FilePath& module_path) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedModuleHandle LoadTestModule(const std::string& module_name) {
|
ScopedModuleHandle LoadTestModule(const std::string& module_name,
|
||||||
|
const std::string& module_soname) {
|
||||||
base::FilePath module_path(
|
base::FilePath module_path(
|
||||||
TestPaths::Executable().DirName().Append(module_name));
|
TestPaths::Executable().DirName().Append(module_name));
|
||||||
|
|
||||||
if (!WriteTestModule(module_path)) {
|
if (!WriteTestModule(module_path, module_soname)) {
|
||||||
return ScopedModuleHandle(nullptr);
|
return ScopedModuleHandle(nullptr);
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(IsRegularFile(module_path));
|
EXPECT_TRUE(IsRegularFile(module_path));
|
||||||
@ -756,7 +765,9 @@ void ExpectTestModule(ProcessReaderLinux* reader,
|
|||||||
|
|
||||||
TEST(ProcessReaderLinux, SelfModules) {
|
TEST(ProcessReaderLinux, SelfModules) {
|
||||||
const std::string module_name = "test_module.so";
|
const std::string module_name = "test_module.so";
|
||||||
ScopedModuleHandle empty_test_module(LoadTestModule(module_name));
|
const std::string module_soname = "test_module_soname";
|
||||||
|
ScopedModuleHandle empty_test_module(
|
||||||
|
LoadTestModule(module_name, module_soname));
|
||||||
ASSERT_TRUE(empty_test_module.valid());
|
ASSERT_TRUE(empty_test_module.valid());
|
||||||
|
|
||||||
FakePtraceConnection connection;
|
FakePtraceConnection connection;
|
||||||
@ -766,12 +777,12 @@ TEST(ProcessReaderLinux, SelfModules) {
|
|||||||
ASSERT_TRUE(process_reader.Initialize(&connection));
|
ASSERT_TRUE(process_reader.Initialize(&connection));
|
||||||
|
|
||||||
ExpectModulesFromSelf(process_reader.Modules());
|
ExpectModulesFromSelf(process_reader.Modules());
|
||||||
ExpectTestModule(&process_reader, module_name);
|
ExpectTestModule(&process_reader, module_soname);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChildModuleTest : public Multiprocess {
|
class ChildModuleTest : public Multiprocess {
|
||||||
public:
|
public:
|
||||||
ChildModuleTest() : Multiprocess(), module_name_("test_module.so") {}
|
ChildModuleTest() : Multiprocess(), module_soname_("test_module_soname") {}
|
||||||
~ChildModuleTest() = default;
|
~ChildModuleTest() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -786,11 +797,12 @@ class ChildModuleTest : public Multiprocess {
|
|||||||
ASSERT_TRUE(process_reader.Initialize(&connection));
|
ASSERT_TRUE(process_reader.Initialize(&connection));
|
||||||
|
|
||||||
ExpectModulesFromSelf(process_reader.Modules());
|
ExpectModulesFromSelf(process_reader.Modules());
|
||||||
ExpectTestModule(&process_reader, module_name_);
|
ExpectTestModule(&process_reader, module_soname_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiprocessChild() override {
|
void MultiprocessChild() override {
|
||||||
ScopedModuleHandle empty_test_module(LoadTestModule(module_name_));
|
ScopedModuleHandle empty_test_module(
|
||||||
|
LoadTestModule("test_module.so", module_soname_));
|
||||||
ASSERT_TRUE(empty_test_module.valid());
|
ASSERT_TRUE(empty_test_module.valid());
|
||||||
|
|
||||||
char c = 0;
|
char c = 0;
|
||||||
@ -799,7 +811,7 @@ class ChildModuleTest : public Multiprocess {
|
|||||||
CheckedReadFileAtEOF(ReadPipeHandle());
|
CheckedReadFileAtEOF(ReadPipeHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string module_name_;
|
const std::string module_soname_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ChildModuleTest);
|
DISALLOW_COPY_AND_ASSIGN(ChildModuleTest);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user