From 3d023a3472e6a0eb1cc09407ff8ad4d2917c0704 Mon Sep 17 00:00:00 2001 From: "thestig@chromium.org" Date: Wed, 23 Apr 2014 20:52:28 +0000 Subject: Linux: Check the CRC32 of the debug link file in the symbol dumper. R=mark@chromium.org Review URL: https://breakpad.appspot.com/1644002 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1320 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/common/linux/dump_symbols.cc | 75 ++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 23 deletions(-) (limited to 'src/common/linux/dump_symbols.cc') diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc index 75dcfd4c..b03bea87 100644 --- a/src/common/linux/dump_symbols.cc +++ b/src/common/linux/dump_symbols.cc @@ -57,6 +57,8 @@ #include "common/dwarf_cfi_to_module.h" #include "common/dwarf_cu_to_module.h" #include "common/dwarf_line_to_module.h" +#include "common/linux/crc32.h" +#include "common/linux/eintr_wrapper.h" #include "common/linux/elfutils.h" #include "common/linux/elfutils-inl.h" #include "common/linux/elf_symbols_to_module.h" @@ -141,7 +143,7 @@ class MmapWrapper { private: bool is_set_; - void *base_; + void* base_; size_t size_; }; @@ -204,8 +206,8 @@ class DumperLineToModule: public DwarfCUToModule::LineToModuleHandler { void StartCompilationUnit(const string& compilation_dir) { compilation_dir_ = compilation_dir; } - void ReadProgram(const char *program, uint64 length, - Module *module, std::vector *lines) { + void ReadProgram(const char* program, uint64 length, + Module* module, std::vector* lines) { DwarfLineToModule handler(module, compilation_dir_, lines); dwarf2reader::LineInfo parser(program, length, byte_reader_, &handler); parser.Start(); @@ -369,7 +371,7 @@ bool LoadELF(const string& obj_file, MmapWrapper* map_wrapper, obj_file.c_str(), strerror(errno)); return false; } - void *obj_base = mmap(NULL, st.st_size, + void* obj_base = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, obj_fd, 0); if (obj_base == MAP_FAILED) { fprintf(stderr, "Failed to mmap ELF file '%s': %s\n", @@ -405,19 +407,19 @@ bool ElfEndianness(const typename ElfClass::Ehdr* elf_header, // Read the .gnu_debuglink and get the debug file name. If anything goes // wrong, return an empty string. -template string ReadDebugLink(const char* debuglink, - size_t debuglink_size, + const size_t debuglink_size, + const bool big_endian, const string& obj_file, const std::vector& debug_dirs) { - size_t debuglink_len = strlen(debuglink) + 5; // '\0' + CRC32. - debuglink_len = 4 * ((debuglink_len + 3) / 4); // Round to nearest 4 bytes. + size_t debuglink_len = strlen(debuglink) + 5; // Include '\0' + CRC32. + debuglink_len = 4 * ((debuglink_len + 3) / 4); // Round up to 4 bytes. // Sanity check. if (debuglink_len != debuglink_size) { fprintf(stderr, "Mismatched .gnu_debuglink string / section size: " "%zx %zx\n", debuglink_len, debuglink_size); - return ""; + return string(); } bool found = false; @@ -428,10 +430,39 @@ string ReadDebugLink(const char* debuglink, const string& debug_dir = *it; debuglink_path = debug_dir + "/" + debuglink; debuglink_fd = open(debuglink_path.c_str(), O_RDONLY); - if (debuglink_fd >= 0) { - found = true; - break; + if (debuglink_fd < 0) + continue; + + FDWrapper debuglink_fd_wrapper(debuglink_fd); + + // The CRC is the last 4 bytes in |debuglink|. + const dwarf2reader::Endianness endianness = big_endian ? + dwarf2reader::ENDIANNESS_BIG : dwarf2reader::ENDIANNESS_LITTLE; + dwarf2reader::ByteReader byte_reader(endianness); + uint32_t expected_crc = + byte_reader.ReadFourBytes(&debuglink[debuglink_size - 4]); + + uint32_t actual_crc = 0; + while (true) { + const size_t kReadSize = 4096; + char buf[kReadSize]; + ssize_t bytes_read = HANDLE_EINTR(read(debuglink_fd, &buf, kReadSize)); + if (bytes_read < 0) { + fprintf(stderr, "Error reading debug ELF file %s.\n", + debuglink_path.c_str()); + return string(); + } + if (bytes_read == 0) + break; + actual_crc = google_breakpad::UpdateCrc32(actual_crc, buf, bytes_read); } + if (actual_crc != expected_crc) { + fprintf(stderr, "Error reading debug ELF file - CRC32 mismatch: %s\n", + debuglink_path.c_str()); + continue; + } + found = true; + break; } if (!found) { @@ -441,13 +472,9 @@ string ReadDebugLink(const char* debuglink, const string debug_dir = *it; fprintf(stderr, " %s/%s\n", debug_dir.c_str(), debuglink); } - return ""; + return string(); } - FDWrapper debuglink_fd_wrapper(debuglink_fd); - // TODO(thestig) check the CRC-32 at the end of the .gnu_debuglink - // section. - return debuglink_path; } @@ -545,7 +572,7 @@ bool LoadSymbols(const string& obj_file, module->SetLoadAddress(loading_addr); info->set_loading_addr(loading_addr, obj_file); - Word debug_section_type = + Word debug_section_type = elf_header->e_machine == EM_MIPS ? SHT_MIPS_DWARF : SHT_PROGBITS; const Shdr* sections = GetOffset(elf_header, elf_header->e_shoff); @@ -657,10 +684,12 @@ bool LoadSymbols(const string& obj_file, const char* debuglink_contents = GetOffset(elf_header, gnu_debuglink_section->sh_offset); - string debuglink_file - = ReadDebugLink(debuglink_contents, - gnu_debuglink_section->sh_size, - obj_file, info->debug_dirs()); + string debuglink_file = + ReadDebugLink(debuglink_contents, + gnu_debuglink_section->sh_size, + big_endian, + obj_file, + info->debug_dirs()); info->set_debuglink_file(debuglink_file); } else { fprintf(stderr, ".gnu_debuglink section found in '%s', " @@ -759,7 +788,7 @@ string FormatIdentifier(unsigned char identifier[16]) { // last slash, or the whole filename if there are no slashes. string BaseFileName(const string &filename) { // Lots of copies! basename's behavior is less than ideal. - char *c_filename = strdup(filename.c_str()); + char* c_filename = strdup(filename.c_str()); string base = basename(c_filename); free(c_filename); return base; -- cgit v1.2.1