toolkit/crashreporter/google-breakpad/src/common/linux/file_id.cc

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 // Copyright (c) 2006, Google Inc.
michael@0 2 // All rights reserved.
michael@0 3 //
michael@0 4 // Redistribution and use in source and binary forms, with or without
michael@0 5 // modification, are permitted provided that the following conditions are
michael@0 6 // met:
michael@0 7 //
michael@0 8 // * Redistributions of source code must retain the above copyright
michael@0 9 // notice, this list of conditions and the following disclaimer.
michael@0 10 // * Redistributions in binary form must reproduce the above
michael@0 11 // copyright notice, this list of conditions and the following disclaimer
michael@0 12 // in the documentation and/or other materials provided with the
michael@0 13 // distribution.
michael@0 14 // * Neither the name of Google Inc. nor the names of its
michael@0 15 // contributors may be used to endorse or promote products derived from
michael@0 16 // this software without specific prior written permission.
michael@0 17 //
michael@0 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
michael@0 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
michael@0 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
michael@0 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
michael@0 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
michael@0 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
michael@0 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
michael@0 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
michael@0 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
michael@0 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
michael@0 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
michael@0 29 //
michael@0 30 // file_id.cc: Return a unique identifier for a file
michael@0 31 //
michael@0 32 // See file_id.h for documentation
michael@0 33 //
michael@0 34
michael@0 35 #include "common/linux/file_id.h"
michael@0 36
michael@0 37 #include <arpa/inet.h>
michael@0 38 #include <assert.h>
michael@0 39 #include <string.h>
michael@0 40
michael@0 41 #include <algorithm>
michael@0 42
michael@0 43 #include "common/linux/elfutils.h"
michael@0 44 #include "common/linux/linux_libc_support.h"
michael@0 45 #include "common/linux/memory_mapped_file.h"
michael@0 46 #include "third_party/lss/linux_syscall_support.h"
michael@0 47
michael@0 48 namespace google_breakpad {
michael@0 49
michael@0 50 #ifndef NT_GNU_BUILD_ID
michael@0 51 #define NT_GNU_BUILD_ID 3
michael@0 52 #endif
michael@0 53
michael@0 54 FileID::FileID(const char* path) {
michael@0 55 strncpy(path_, path, sizeof(path_));
michael@0 56 }
michael@0 57
michael@0 58 // ELF note name and desc are 32-bits word padded.
michael@0 59 #define NOTE_PADDING(a) ((a + 3) & ~3)
michael@0 60
michael@0 61 // These functions are also used inside the crashed process, so be safe
michael@0 62 // and use the syscall/libc wrappers instead of direct syscalls or libc.
michael@0 63
michael@0 64 template<typename ElfClass>
michael@0 65 static bool ElfClassBuildIDNoteIdentifier(const void *section, int length,
michael@0 66 uint8_t identifier[kMDGUIDSize]) {
michael@0 67 typedef typename ElfClass::Nhdr Nhdr;
michael@0 68
michael@0 69 const void* section_end = reinterpret_cast<const char*>(section) + length;
michael@0 70 const Nhdr* note_header = reinterpret_cast<const Nhdr*>(section);
michael@0 71 while (reinterpret_cast<const void *>(note_header) < section_end) {
michael@0 72 if (note_header->n_type == NT_GNU_BUILD_ID)
michael@0 73 break;
michael@0 74 note_header = reinterpret_cast<const Nhdr*>(
michael@0 75 reinterpret_cast<const char*>(note_header) + sizeof(Nhdr) +
michael@0 76 NOTE_PADDING(note_header->n_namesz) +
michael@0 77 NOTE_PADDING(note_header->n_descsz));
michael@0 78 }
michael@0 79 if (reinterpret_cast<const void *>(note_header) >= section_end ||
michael@0 80 note_header->n_descsz == 0) {
michael@0 81 return false;
michael@0 82 }
michael@0 83
michael@0 84 const char* build_id = reinterpret_cast<const char*>(note_header) +
michael@0 85 sizeof(Nhdr) + NOTE_PADDING(note_header->n_namesz);
michael@0 86 // Copy as many bits of the build ID as will fit
michael@0 87 // into the GUID space.
michael@0 88 my_memset(identifier, 0, kMDGUIDSize);
michael@0 89 memcpy(identifier, build_id,
michael@0 90 std::min(kMDGUIDSize, (size_t)note_header->n_descsz));
michael@0 91
michael@0 92 return true;
michael@0 93 }
michael@0 94
michael@0 95 // Attempt to locate a .note.gnu.build-id section in an ELF binary
michael@0 96 // and copy as many bytes of it as will fit into |identifier|.
michael@0 97 static bool FindElfBuildIDNote(const void *elf_mapped_base,
michael@0 98 uint8_t identifier[kMDGUIDSize]) {
michael@0 99 void* note_section;
michael@0 100 int note_size, elfclass;
michael@0 101 if ((!FindElfSegment(elf_mapped_base, PT_NOTE,
michael@0 102 (const void**)&note_section, &note_size, &elfclass) ||
michael@0 103 note_size == 0) &&
michael@0 104 (!FindElfSection(elf_mapped_base, ".note.gnu.build-id", SHT_NOTE,
michael@0 105 (const void**)&note_section, &note_size, &elfclass) ||
michael@0 106 note_size == 0)) {
michael@0 107 return false;
michael@0 108 }
michael@0 109
michael@0 110 if (elfclass == ELFCLASS32) {
michael@0 111 return ElfClassBuildIDNoteIdentifier<ElfClass32>(note_section, note_size,
michael@0 112 identifier);
michael@0 113 } else if (elfclass == ELFCLASS64) {
michael@0 114 return ElfClassBuildIDNoteIdentifier<ElfClass64>(note_section, note_size,
michael@0 115 identifier);
michael@0 116 }
michael@0 117
michael@0 118 return false;
michael@0 119 }
michael@0 120
michael@0 121 // Attempt to locate the .text section of an ELF binary and generate
michael@0 122 // a simple hash by XORing the first page worth of bytes into |identifier|.
michael@0 123 static bool HashElfTextSection(const void *elf_mapped_base,
michael@0 124 uint8_t identifier[kMDGUIDSize]) {
michael@0 125 void* text_section;
michael@0 126 int text_size;
michael@0 127 if (!FindElfSection(elf_mapped_base, ".text", SHT_PROGBITS,
michael@0 128 (const void**)&text_section, &text_size, NULL) ||
michael@0 129 text_size == 0) {
michael@0 130 return false;
michael@0 131 }
michael@0 132
michael@0 133 my_memset(identifier, 0, kMDGUIDSize);
michael@0 134 const uint8_t* ptr = reinterpret_cast<const uint8_t*>(text_section);
michael@0 135 const uint8_t* ptr_end = ptr + std::min(text_size, 4096);
michael@0 136 while (ptr < ptr_end) {
michael@0 137 for (unsigned i = 0; i < kMDGUIDSize; i++)
michael@0 138 identifier[i] ^= ptr[i];
michael@0 139 ptr += kMDGUIDSize;
michael@0 140 }
michael@0 141 return true;
michael@0 142 }
michael@0 143
michael@0 144 // static
michael@0 145 bool FileID::ElfFileIdentifierFromMappedFile(const void* base,
michael@0 146 uint8_t identifier[kMDGUIDSize]) {
michael@0 147 // Look for a build id note first.
michael@0 148 if (FindElfBuildIDNote(base, identifier))
michael@0 149 return true;
michael@0 150
michael@0 151 // Fall back on hashing the first page of the text section.
michael@0 152 return HashElfTextSection(base, identifier);
michael@0 153 }
michael@0 154
michael@0 155 bool FileID::ElfFileIdentifier(uint8_t identifier[kMDGUIDSize]) {
michael@0 156 MemoryMappedFile mapped_file(path_);
michael@0 157 if (!mapped_file.data()) // Should probably check if size >= ElfW(Ehdr)?
michael@0 158 return false;
michael@0 159
michael@0 160 return ElfFileIdentifierFromMappedFile(mapped_file.data(), identifier);
michael@0 161 }
michael@0 162
michael@0 163 // static
michael@0 164 void FileID::ConvertIdentifierToString(const uint8_t identifier[kMDGUIDSize],
michael@0 165 char* buffer, int buffer_length) {
michael@0 166 uint8_t identifier_swapped[kMDGUIDSize];
michael@0 167
michael@0 168 // Endian-ness swap to match dump processor expectation.
michael@0 169 memcpy(identifier_swapped, identifier, kMDGUIDSize);
michael@0 170 uint32_t* data1 = reinterpret_cast<uint32_t*>(identifier_swapped);
michael@0 171 *data1 = htonl(*data1);
michael@0 172 uint16_t* data2 = reinterpret_cast<uint16_t*>(identifier_swapped + 4);
michael@0 173 *data2 = htons(*data2);
michael@0 174 uint16_t* data3 = reinterpret_cast<uint16_t*>(identifier_swapped + 6);
michael@0 175 *data3 = htons(*data3);
michael@0 176
michael@0 177 int buffer_idx = 0;
michael@0 178 for (unsigned int idx = 0;
michael@0 179 (buffer_idx < buffer_length) && (idx < kMDGUIDSize);
michael@0 180 ++idx) {
michael@0 181 int hi = (identifier_swapped[idx] >> 4) & 0x0F;
michael@0 182 int lo = (identifier_swapped[idx]) & 0x0F;
michael@0 183
michael@0 184 if (idx == 4 || idx == 6 || idx == 8 || idx == 10)
michael@0 185 buffer[buffer_idx++] = '-';
michael@0 186
michael@0 187 buffer[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi;
michael@0 188 buffer[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo;
michael@0 189 }
michael@0 190
michael@0 191 // NULL terminate
michael@0 192 buffer[(buffer_idx < buffer_length) ? buffer_idx : buffer_idx - 1] = 0;
michael@0 193 }
michael@0 194
michael@0 195 } // namespace google_breakpad

mercurial