Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/processor/exploitability_linux.cc

Issue 1251593007: Add support for Linux memory mapping stream and remove ELF header usage (Closed) Base URL: http://google-breakpad.googlecode.com/svn/trunk/
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 Google Inc. 1 // Copyright (c) 2013 Google Inc.
2 // All rights reserved. 2 // All rights reserved.
3 // 3 //
4 // Redistribution and use in source and binary forms, with or without 4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are 5 // modification, are permitted provided that the following conditions are
6 // met: 6 // met:
7 // 7 //
8 // * Redistributions of source code must retain the above copyright 8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer. 9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above 10 // * Redistributions in binary form must reproduce the above
(...skipping 18 matching lines...) Expand all
29 29
30 // exploitability_linux.cc: Linux specific exploitability engine. 30 // exploitability_linux.cc: Linux specific exploitability engine.
31 // 31 //
32 // Provides a guess at the exploitability of the crash for the Linux 32 // Provides a guess at the exploitability of the crash for the Linux
33 // platform given a minidump and process_state. 33 // platform given a minidump and process_state.
34 // 34 //
35 // Author: Matthew Riley 35 // Author: Matthew Riley
36 36
37 #include "processor/exploitability_linux.h" 37 #include "processor/exploitability_linux.h"
38 38
39 #include <elf.h>
40
41 #include "google_breakpad/common/minidump_exception_linux.h" 39 #include "google_breakpad/common/minidump_exception_linux.h"
42 #include "google_breakpad/processor/call_stack.h" 40 #include "google_breakpad/processor/call_stack.h"
43 #include "google_breakpad/processor/process_state.h" 41 #include "google_breakpad/processor/process_state.h"
44 #include "google_breakpad/processor/stack_frame.h" 42 #include "google_breakpad/processor/stack_frame.h"
45 #include "processor/logging.h" 43 #include "processor/logging.h"
46 44
47 namespace { 45 namespace {
48 46
49 // This function in libc is called if the program was compiled with 47 // This function in libc is called if the program was compiled with
50 // -fstack-protector and a function's stack canary changes. 48 // -fstack-protector and a function's stack canary changes.
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 return LINUX_64_BIT; 152 return LINUX_64_BIT;
155 default: 153 default:
156 // This should not happen. The four architectures above should be 154 // This should not happen. The four architectures above should be
157 // the only Linux architectures. 155 // the only Linux architectures.
158 BPLOG(INFO) << "Unsupported architecture."; 156 BPLOG(INFO) << "Unsupported architecture.";
159 return UNSUPPORTED_ARCHITECTURE; 157 return UNSUPPORTED_ARCHITECTURE;
160 } 158 }
161 } 159 }
162 160
163 bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr) { 161 bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr) {
164 // Get memory mapping. Most minidumps will not contain a memory 162 // Get Linux memory mapping from /proc/self/maps. Checking whether the
165 // mapping, so processing will commonly resort to checking modules. 163 // region the instruction pointer is in has executable permission can tell
166 MinidumpMemoryInfoList *mem_info_list = dump_->GetMemoryInfoList(); 164 // whether it is in a valid code region. If there is no mapping for the
167 const MinidumpMemoryInfo *mem_info = 165 // instruction pointer, it is indicative that the instruction pointer is
168 mem_info_list ? 166 // not within a module, which implies that it is outside a valid area.
169 mem_info_list->GetMemoryInfoForAddress(instruction_ptr) : NULL; 167 MinidumpLinuxMapsList *linux_maps_list = dump_->GetLinuxMapsList();
170 168 const MinidumpLinuxMaps *linux_maps =
171 // Check if the memory mapping at the instruction pointer is executable. 169 linux_maps_list ?
172 // If there is no memory mapping, processing will use modules as reference. 170 linux_maps_list->GetLinuxMapsForAddress(instruction_ptr) : NULL;
173 if (mem_info != NULL) { 171 return linux_maps ? linux_maps->IsExecutable() : false;
174 return mem_info->IsExecutable();
175 }
176
177 // If the memory mapping retrieval fails, check the modules
178 // to see if the instruction pointer is inside a module.
179 MinidumpModuleList *minidump_module_list = dump_->GetModuleList();
180 const MinidumpModule *minidump_module =
181 minidump_module_list ?
182 minidump_module_list->GetModuleForAddress(instruction_ptr) : NULL;
183
184 // If the instruction pointer isn't in a module, return false.
185 if (minidump_module == NULL) {
186 return false;
187 }
188
189 // Get ELF header data from the instruction pointer's module.
190 const uint64_t base_address = minidump_module->base_address();
191 MinidumpMemoryList *memory_list = dump_->GetMemoryList();
192 MinidumpMemoryRegion *memory_region =
193 memory_list ?
194 memory_list->GetMemoryRegionForAddress(base_address) : NULL;
195
196 // The minidump does not have the correct memory region.
197 // This returns true because even though there is no memory data available,
198 // the evidence so far suggests that the instruction pointer is not at a
199 // bad location.
200 if (memory_region == NULL) {
201 return true;
202 }
203
204 // Examine ELF headers. Depending on the architecture, the size of the
205 // ELF headers can differ.
206 LinuxArchitectureType architecture = this->ArchitectureType();
207 if (architecture == LINUX_32_BIT) {
208 // Check if the ELF header is within the memory region and if the
209 // instruction pointer lies within the ELF header.
210 if (memory_region->GetSize() < sizeof(Elf32_Ehdr) ||
211 instruction_ptr < base_address + sizeof(Elf32_Ehdr)) {
212 return false;
213 }
214 // Load 32-bit ELF header.
215 Elf32_Ehdr header;
216 this->LoadElfHeader(memory_region, base_address, &header);
217 // Check if the program header table is within the memory region, and
218 // validate that the program header entry size is correct.
219 if (header.e_phentsize != sizeof(Elf32_Phdr) ||
220 memory_region->GetSize() <
221 header.e_phoff +
222 ((uint64_t) header.e_phentsize * (uint64_t) header.e_phnum)) {
223 return false;
224 }
225 // Load 32-bit Program Header Table.
226 scoped_array<Elf32_Phdr> program_headers(new Elf32_Phdr[header.e_phnum]);
227 this->LoadElfHeaderTable(memory_region,
228 base_address + header.e_phoff,
229 header.e_phnum,
230 program_headers.get());
231 // Find correct program header that corresponds to the instruction pointer.
232 for (int i = 0; i < header.e_phnum; i++) {
233 const Elf32_Phdr& program_header = program_headers[i];
234 // Check if instruction pointer lies within this program header's region.
235 if (instruction_ptr >= program_header.p_vaddr &&
236 instruction_ptr < program_header.p_vaddr + program_header.p_memsz) {
237 // Return whether this program header region is executable.
238 return program_header.p_flags & PF_X;
239 }
240 }
241 } else if (architecture == LINUX_64_BIT) {
242 // Check if the ELF header is within the memory region and if the
243 // instruction pointer lies within the ELF header.
244 if (memory_region->GetSize() < sizeof(Elf64_Ehdr) ||
245 instruction_ptr < base_address + sizeof(Elf64_Ehdr)) {
246 return false;
247 }
248 // Load 64-bit ELF header.
249 Elf64_Ehdr header;
250 this->LoadElfHeader(memory_region, base_address, &header);
ivanpe 2015/07/23 01:17:12 Please, make sure to cleanup all functions that ar
liuandrew 2015/07/24 23:25:36 Done.
251 // Check if the program header table is within the memory region, and
252 // validate that the program header entry size is correct.
253 if (header.e_phentsize != sizeof(Elf64_Phdr) ||
254 memory_region->GetSize() <
255 header.e_phoff +
256 ((uint64_t) header.e_phentsize * (uint64_t) header.e_phnum)) {
257 return false;
258 }
259 // Load 64-bit Program Header Table.
260 scoped_array<Elf64_Phdr> program_headers(new Elf64_Phdr[header.e_phnum]);
261 this->LoadElfHeaderTable(memory_region,
262 base_address + header.e_phoff,
263 header.e_phnum,
264 program_headers.get());
265 // Find correct program header that corresponds to the instruction pointer.
266 for (int i = 0; i < header.e_phnum; i++) {
267 const Elf64_Phdr& program_header = program_headers[i];
268 // Check if instruction pointer lies within this program header's region.
269 if (instruction_ptr >= program_header.p_vaddr &&
270 instruction_ptr < program_header.p_vaddr + program_header.p_memsz) {
271 // Return whether this program header region is executable.
272 return program_header.p_flags & PF_X;
273 }
274 }
275 }
276
277 // The instruction pointer was not in an area identified by the ELF headers.
278 return false;
279 } 172 }
280 173
281 bool ExploitabilityLinux::BenignCrashTrigger(const MDRawExceptionStream 174 bool ExploitabilityLinux::BenignCrashTrigger(const MDRawExceptionStream
282 *raw_exception_stream) { 175 *raw_exception_stream) {
283 // Check the cause of crash. 176 // Check the cause of crash.
284 // If the exception of the crash is a benign exception, 177 // If the exception of the crash is a benign exception,
285 // it is probably not exploitable. 178 // it is probably not exploitable.
286 switch (raw_exception_stream->exception_record.exception_code) { 179 switch (raw_exception_stream->exception_record.exception_code) {
287 case MD_EXCEPTION_CODE_LIN_SIGHUP: 180 case MD_EXCEPTION_CODE_LIN_SIGHUP:
288 case MD_EXCEPTION_CODE_LIN_SIGINT: 181 case MD_EXCEPTION_CODE_LIN_SIGINT:
(...skipping 25 matching lines...) Expand all
314 case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED: 207 case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED:
315 return true; 208 return true;
316 break; 209 break;
317 default: 210 default:
318 return false; 211 return false;
319 break; 212 break;
320 } 213 }
321 } 214 }
322 215
323 } // namespace google_breakpad 216 } // namespace google_breakpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698