aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/proc/vmcore.c359
1 files changed, 286 insertions, 73 deletions
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index 78c87a1ac01a..9b9270eb0599 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -34,6 +34,9 @@ static char *elfcorebuf;
34static size_t elfcorebuf_sz; 34static size_t elfcorebuf_sz;
35static size_t elfcorebuf_sz_orig; 35static size_t elfcorebuf_sz_orig;
36 36
37static char *elfnotes_buf;
38static size_t elfnotes_sz;
39
37/* Total size of vmcore file. */ 40/* Total size of vmcore file. */
38static u64 vmcore_size; 41static u64 vmcore_size;
39 42
@@ -139,9 +142,7 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
139 142
140 /* Read ELF core header */ 143 /* Read ELF core header */
141 if (*fpos < elfcorebuf_sz) { 144 if (*fpos < elfcorebuf_sz) {
142 tsz = elfcorebuf_sz - *fpos; 145 tsz = min(elfcorebuf_sz - (size_t)*fpos, buflen);
143 if (buflen < tsz)
144 tsz = buflen;
145 if (copy_to_user(buffer, elfcorebuf + *fpos, tsz)) 146 if (copy_to_user(buffer, elfcorebuf + *fpos, tsz))
146 return -EFAULT; 147 return -EFAULT;
147 buflen -= tsz; 148 buflen -= tsz;
@@ -154,11 +155,27 @@ static ssize_t read_vmcore(struct file *file, char __user *buffer,
154 return acc; 155 return acc;
155 } 156 }
156 157
158 /* Read Elf note segment */
159 if (*fpos < elfcorebuf_sz + elfnotes_sz) {
160 void *kaddr;
161
162 tsz = min(elfcorebuf_sz + elfnotes_sz - (size_t)*fpos, buflen);
163 kaddr = elfnotes_buf + *fpos - elfcorebuf_sz;
164 if (copy_to_user(buffer, kaddr, tsz))
165 return -EFAULT;
166 buflen -= tsz;
167 *fpos += tsz;
168 buffer += tsz;
169 acc += tsz;
170
171 /* leave now if filled buffer already */
172 if (buflen == 0)
173 return acc;
174 }
175
157 list_for_each_entry(m, &vmcore_list, list) { 176 list_for_each_entry(m, &vmcore_list, list) {
158 if (*fpos < m->offset + m->size) { 177 if (*fpos < m->offset + m->size) {
159 tsz = m->offset + m->size - *fpos; 178 tsz = min_t(size_t, m->offset + m->size - *fpos, buflen);
160 if (buflen < tsz)
161 tsz = buflen;
162 start = m->paddr + *fpos - m->offset; 179 start = m->paddr + *fpos - m->offset;
163 tmp = read_from_oldmem(buffer, tsz, &start, 1); 180 tmp = read_from_oldmem(buffer, tsz, &start, 1);
164 if (tmp < 0) 181 if (tmp < 0)
@@ -221,27 +238,27 @@ static u64 __init get_vmcore_size_elf32(char *elfptr, size_t elfsz)
221 return size; 238 return size;
222} 239}
223 240
224/* Merges all the PT_NOTE headers into one. */ 241/**
225static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz, 242 * update_note_header_size_elf64 - update p_memsz member of each PT_NOTE entry
226 struct list_head *vc_list) 243 *
244 * @ehdr_ptr: ELF header
245 *
246 * This function updates p_memsz member of each PT_NOTE entry in the
247 * program header table pointed to by @ehdr_ptr to real size of ELF
248 * note segment.
249 */
250static int __init update_note_header_size_elf64(const Elf64_Ehdr *ehdr_ptr)
227{ 251{
228 int i, nr_ptnote=0, rc=0; 252 int i, rc=0;
229 char *tmp; 253 Elf64_Phdr *phdr_ptr;
230 Elf64_Ehdr *ehdr_ptr;
231 Elf64_Phdr phdr, *phdr_ptr;
232 Elf64_Nhdr *nhdr_ptr; 254 Elf64_Nhdr *nhdr_ptr;
233 u64 phdr_sz = 0, note_off;
234 255
235 ehdr_ptr = (Elf64_Ehdr *)elfptr; 256 phdr_ptr = (Elf64_Phdr *)(ehdr_ptr + 1);
236 phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr));
237 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) { 257 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
238 int j;
239 void *notes_section; 258 void *notes_section;
240 struct vmcore *new;
241 u64 offset, max_sz, sz, real_sz = 0; 259 u64 offset, max_sz, sz, real_sz = 0;
242 if (phdr_ptr->p_type != PT_NOTE) 260 if (phdr_ptr->p_type != PT_NOTE)
243 continue; 261 continue;
244 nr_ptnote++;
245 max_sz = phdr_ptr->p_memsz; 262 max_sz = phdr_ptr->p_memsz;
246 offset = phdr_ptr->p_offset; 263 offset = phdr_ptr->p_offset;
247 notes_section = kmalloc(max_sz, GFP_KERNEL); 264 notes_section = kmalloc(max_sz, GFP_KERNEL);
@@ -253,7 +270,7 @@ static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz,
253 return rc; 270 return rc;
254 } 271 }
255 nhdr_ptr = notes_section; 272 nhdr_ptr = notes_section;
256 for (j = 0; j < max_sz; j += sz) { 273 while (real_sz < max_sz) {
257 if (nhdr_ptr->n_namesz == 0) 274 if (nhdr_ptr->n_namesz == 0)
258 break; 275 break;
259 sz = sizeof(Elf64_Nhdr) + 276 sz = sizeof(Elf64_Nhdr) +
@@ -262,26 +279,122 @@ static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz,
262 real_sz += sz; 279 real_sz += sz;
263 nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz); 280 nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz);
264 } 281 }
265
266 /* Add this contiguous chunk of notes section to vmcore list.*/
267 new = get_new_element();
268 if (!new) {
269 kfree(notes_section);
270 return -ENOMEM;
271 }
272 new->paddr = phdr_ptr->p_offset;
273 new->size = real_sz;
274 list_add_tail(&new->list, vc_list);
275 phdr_sz += real_sz;
276 kfree(notes_section); 282 kfree(notes_section);
283 phdr_ptr->p_memsz = real_sz;
277 } 284 }
278 285
286 return 0;
287}
288
289/**
290 * get_note_number_and_size_elf64 - get the number of PT_NOTE program
291 * headers and sum of real size of their ELF note segment headers and
292 * data.
293 *
294 * @ehdr_ptr: ELF header
295 * @nr_ptnote: buffer for the number of PT_NOTE program headers
296 * @sz_ptnote: buffer for size of unique PT_NOTE program header
297 *
298 * This function is used to merge multiple PT_NOTE program headers
299 * into a unique single one. The resulting unique entry will have
300 * @sz_ptnote in its phdr->p_mem.
301 *
302 * It is assumed that program headers with PT_NOTE type pointed to by
303 * @ehdr_ptr has already been updated by update_note_header_size_elf64
304 * and each of PT_NOTE program headers has actual ELF note segment
305 * size in its p_memsz member.
306 */
307static int __init get_note_number_and_size_elf64(const Elf64_Ehdr *ehdr_ptr,
308 int *nr_ptnote, u64 *sz_ptnote)
309{
310 int i;
311 Elf64_Phdr *phdr_ptr;
312
313 *nr_ptnote = *sz_ptnote = 0;
314
315 phdr_ptr = (Elf64_Phdr *)(ehdr_ptr + 1);
316 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
317 if (phdr_ptr->p_type != PT_NOTE)
318 continue;
319 *nr_ptnote += 1;
320 *sz_ptnote += phdr_ptr->p_memsz;
321 }
322
323 return 0;
324}
325
326/**
327 * copy_notes_elf64 - copy ELF note segments in a given buffer
328 *
329 * @ehdr_ptr: ELF header
330 * @notes_buf: buffer into which ELF note segments are copied
331 *
332 * This function is used to copy ELF note segment in the 1st kernel
333 * into the buffer @notes_buf in the 2nd kernel. It is assumed that
334 * size of the buffer @notes_buf is equal to or larger than sum of the
335 * real ELF note segment headers and data.
336 *
337 * It is assumed that program headers with PT_NOTE type pointed to by
338 * @ehdr_ptr has already been updated by update_note_header_size_elf64
339 * and each of PT_NOTE program headers has actual ELF note segment
340 * size in its p_memsz member.
341 */
342static int __init copy_notes_elf64(const Elf64_Ehdr *ehdr_ptr, char *notes_buf)
343{
344 int i, rc=0;
345 Elf64_Phdr *phdr_ptr;
346
347 phdr_ptr = (Elf64_Phdr*)(ehdr_ptr + 1);
348
349 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
350 u64 offset;
351 if (phdr_ptr->p_type != PT_NOTE)
352 continue;
353 offset = phdr_ptr->p_offset;
354 rc = read_from_oldmem(notes_buf, phdr_ptr->p_memsz, &offset, 0);
355 if (rc < 0)
356 return rc;
357 notes_buf += phdr_ptr->p_memsz;
358 }
359
360 return 0;
361}
362
363/* Merges all the PT_NOTE headers into one. */
364static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz,
365 char **notes_buf, size_t *notes_sz)
366{
367 int i, nr_ptnote=0, rc=0;
368 char *tmp;
369 Elf64_Ehdr *ehdr_ptr;
370 Elf64_Phdr phdr;
371 u64 phdr_sz = 0, note_off;
372
373 ehdr_ptr = (Elf64_Ehdr *)elfptr;
374
375 rc = update_note_header_size_elf64(ehdr_ptr);
376 if (rc < 0)
377 return rc;
378
379 rc = get_note_number_and_size_elf64(ehdr_ptr, &nr_ptnote, &phdr_sz);
380 if (rc < 0)
381 return rc;
382
383 *notes_sz = roundup(phdr_sz, PAGE_SIZE);
384 *notes_buf = vzalloc(*notes_sz);
385 if (!*notes_buf)
386 return -ENOMEM;
387
388 rc = copy_notes_elf64(ehdr_ptr, *notes_buf);
389 if (rc < 0)
390 return rc;
391
279 /* Prepare merged PT_NOTE program header. */ 392 /* Prepare merged PT_NOTE program header. */
280 phdr.p_type = PT_NOTE; 393 phdr.p_type = PT_NOTE;
281 phdr.p_flags = 0; 394 phdr.p_flags = 0;
282 note_off = sizeof(Elf64_Ehdr) + 395 note_off = sizeof(Elf64_Ehdr) +
283 (ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf64_Phdr); 396 (ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf64_Phdr);
284 phdr.p_offset = note_off; 397 phdr.p_offset = roundup(note_off, PAGE_SIZE);
285 phdr.p_vaddr = phdr.p_paddr = 0; 398 phdr.p_vaddr = phdr.p_paddr = 0;
286 phdr.p_filesz = phdr.p_memsz = phdr_sz; 399 phdr.p_filesz = phdr.p_memsz = phdr_sz;
287 phdr.p_align = 0; 400 phdr.p_align = 0;
@@ -304,27 +417,27 @@ static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz,
304 return 0; 417 return 0;
305} 418}
306 419
307/* Merges all the PT_NOTE headers into one. */ 420/**
308static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz, 421 * update_note_header_size_elf32 - update p_memsz member of each PT_NOTE entry
309 struct list_head *vc_list) 422 *
423 * @ehdr_ptr: ELF header
424 *
425 * This function updates p_memsz member of each PT_NOTE entry in the
426 * program header table pointed to by @ehdr_ptr to real size of ELF
427 * note segment.
428 */
429static int __init update_note_header_size_elf32(const Elf32_Ehdr *ehdr_ptr)
310{ 430{
311 int i, nr_ptnote=0, rc=0; 431 int i, rc=0;
312 char *tmp; 432 Elf32_Phdr *phdr_ptr;
313 Elf32_Ehdr *ehdr_ptr;
314 Elf32_Phdr phdr, *phdr_ptr;
315 Elf32_Nhdr *nhdr_ptr; 433 Elf32_Nhdr *nhdr_ptr;
316 u64 phdr_sz = 0, note_off;
317 434
318 ehdr_ptr = (Elf32_Ehdr *)elfptr; 435 phdr_ptr = (Elf32_Phdr *)(ehdr_ptr + 1);
319 phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr));
320 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) { 436 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
321 int j;
322 void *notes_section; 437 void *notes_section;
323 struct vmcore *new;
324 u64 offset, max_sz, sz, real_sz = 0; 438 u64 offset, max_sz, sz, real_sz = 0;
325 if (phdr_ptr->p_type != PT_NOTE) 439 if (phdr_ptr->p_type != PT_NOTE)
326 continue; 440 continue;
327 nr_ptnote++;
328 max_sz = phdr_ptr->p_memsz; 441 max_sz = phdr_ptr->p_memsz;
329 offset = phdr_ptr->p_offset; 442 offset = phdr_ptr->p_offset;
330 notes_section = kmalloc(max_sz, GFP_KERNEL); 443 notes_section = kmalloc(max_sz, GFP_KERNEL);
@@ -336,7 +449,7 @@ static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz,
336 return rc; 449 return rc;
337 } 450 }
338 nhdr_ptr = notes_section; 451 nhdr_ptr = notes_section;
339 for (j = 0; j < max_sz; j += sz) { 452 while (real_sz < max_sz) {
340 if (nhdr_ptr->n_namesz == 0) 453 if (nhdr_ptr->n_namesz == 0)
341 break; 454 break;
342 sz = sizeof(Elf32_Nhdr) + 455 sz = sizeof(Elf32_Nhdr) +
@@ -345,26 +458,122 @@ static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz,
345 real_sz += sz; 458 real_sz += sz;
346 nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz); 459 nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz);
347 } 460 }
348
349 /* Add this contiguous chunk of notes section to vmcore list.*/
350 new = get_new_element();
351 if (!new) {
352 kfree(notes_section);
353 return -ENOMEM;
354 }
355 new->paddr = phdr_ptr->p_offset;
356 new->size = real_sz;
357 list_add_tail(&new->list, vc_list);
358 phdr_sz += real_sz;
359 kfree(notes_section); 461 kfree(notes_section);
462 phdr_ptr->p_memsz = real_sz;
463 }
464
465 return 0;
466}
467
468/**
469 * get_note_number_and_size_elf32 - get the number of PT_NOTE program
470 * headers and sum of real size of their ELF note segment headers and
471 * data.
472 *
473 * @ehdr_ptr: ELF header
474 * @nr_ptnote: buffer for the number of PT_NOTE program headers
475 * @sz_ptnote: buffer for size of unique PT_NOTE program header
476 *
477 * This function is used to merge multiple PT_NOTE program headers
478 * into a unique single one. The resulting unique entry will have
479 * @sz_ptnote in its phdr->p_mem.
480 *
481 * It is assumed that program headers with PT_NOTE type pointed to by
482 * @ehdr_ptr has already been updated by update_note_header_size_elf32
483 * and each of PT_NOTE program headers has actual ELF note segment
484 * size in its p_memsz member.
485 */
486static int __init get_note_number_and_size_elf32(const Elf32_Ehdr *ehdr_ptr,
487 int *nr_ptnote, u64 *sz_ptnote)
488{
489 int i;
490 Elf32_Phdr *phdr_ptr;
491
492 *nr_ptnote = *sz_ptnote = 0;
493
494 phdr_ptr = (Elf32_Phdr *)(ehdr_ptr + 1);
495 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
496 if (phdr_ptr->p_type != PT_NOTE)
497 continue;
498 *nr_ptnote += 1;
499 *sz_ptnote += phdr_ptr->p_memsz;
360 } 500 }
361 501
502 return 0;
503}
504
505/**
506 * copy_notes_elf32 - copy ELF note segments in a given buffer
507 *
508 * @ehdr_ptr: ELF header
509 * @notes_buf: buffer into which ELF note segments are copied
510 *
511 * This function is used to copy ELF note segment in the 1st kernel
512 * into the buffer @notes_buf in the 2nd kernel. It is assumed that
513 * size of the buffer @notes_buf is equal to or larger than sum of the
514 * real ELF note segment headers and data.
515 *
516 * It is assumed that program headers with PT_NOTE type pointed to by
517 * @ehdr_ptr has already been updated by update_note_header_size_elf32
518 * and each of PT_NOTE program headers has actual ELF note segment
519 * size in its p_memsz member.
520 */
521static int __init copy_notes_elf32(const Elf32_Ehdr *ehdr_ptr, char *notes_buf)
522{
523 int i, rc=0;
524 Elf32_Phdr *phdr_ptr;
525
526 phdr_ptr = (Elf32_Phdr*)(ehdr_ptr + 1);
527
528 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
529 u64 offset;
530 if (phdr_ptr->p_type != PT_NOTE)
531 continue;
532 offset = phdr_ptr->p_offset;
533 rc = read_from_oldmem(notes_buf, phdr_ptr->p_memsz, &offset, 0);
534 if (rc < 0)
535 return rc;
536 notes_buf += phdr_ptr->p_memsz;
537 }
538
539 return 0;
540}
541
542/* Merges all the PT_NOTE headers into one. */
543static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz,
544 char **notes_buf, size_t *notes_sz)
545{
546 int i, nr_ptnote=0, rc=0;
547 char *tmp;
548 Elf32_Ehdr *ehdr_ptr;
549 Elf32_Phdr phdr;
550 u64 phdr_sz = 0, note_off;
551
552 ehdr_ptr = (Elf32_Ehdr *)elfptr;
553
554 rc = update_note_header_size_elf32(ehdr_ptr);
555 if (rc < 0)
556 return rc;
557
558 rc = get_note_number_and_size_elf32(ehdr_ptr, &nr_ptnote, &phdr_sz);
559 if (rc < 0)
560 return rc;
561
562 *notes_sz = roundup(phdr_sz, PAGE_SIZE);
563 *notes_buf = vzalloc(*notes_sz);
564 if (!*notes_buf)
565 return -ENOMEM;
566
567 rc = copy_notes_elf32(ehdr_ptr, *notes_buf);
568 if (rc < 0)
569 return rc;
570
362 /* Prepare merged PT_NOTE program header. */ 571 /* Prepare merged PT_NOTE program header. */
363 phdr.p_type = PT_NOTE; 572 phdr.p_type = PT_NOTE;
364 phdr.p_flags = 0; 573 phdr.p_flags = 0;
365 note_off = sizeof(Elf32_Ehdr) + 574 note_off = sizeof(Elf32_Ehdr) +
366 (ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf32_Phdr); 575 (ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf32_Phdr);
367 phdr.p_offset = note_off; 576 phdr.p_offset = roundup(note_off, PAGE_SIZE);
368 phdr.p_vaddr = phdr.p_paddr = 0; 577 phdr.p_vaddr = phdr.p_paddr = 0;
369 phdr.p_filesz = phdr.p_memsz = phdr_sz; 578 phdr.p_filesz = phdr.p_memsz = phdr_sz;
370 phdr.p_align = 0; 579 phdr.p_align = 0;
@@ -391,6 +600,7 @@ static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz,
391 * the new offset fields of exported program headers. */ 600 * the new offset fields of exported program headers. */
392static int __init process_ptload_program_headers_elf64(char *elfptr, 601static int __init process_ptload_program_headers_elf64(char *elfptr,
393 size_t elfsz, 602 size_t elfsz,
603 size_t elfnotes_sz,
394 struct list_head *vc_list) 604 struct list_head *vc_list)
395{ 605{
396 int i; 606 int i;
@@ -402,9 +612,8 @@ static int __init process_ptload_program_headers_elf64(char *elfptr,
402 ehdr_ptr = (Elf64_Ehdr *)elfptr; 612 ehdr_ptr = (Elf64_Ehdr *)elfptr;
403 phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr)); /* PT_NOTE hdr */ 613 phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr)); /* PT_NOTE hdr */
404 614
405 /* First program header is PT_NOTE header. */ 615 /* Skip Elf header, program headers and Elf note segment. */
406 vmcore_off = elfsz + 616 vmcore_off = elfsz + elfnotes_sz;
407 phdr_ptr->p_memsz; /* Note sections */
408 617
409 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) { 618 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
410 u64 paddr, start, end, size; 619 u64 paddr, start, end, size;
@@ -434,6 +643,7 @@ static int __init process_ptload_program_headers_elf64(char *elfptr,
434 643
435static int __init process_ptload_program_headers_elf32(char *elfptr, 644static int __init process_ptload_program_headers_elf32(char *elfptr,
436 size_t elfsz, 645 size_t elfsz,
646 size_t elfnotes_sz,
437 struct list_head *vc_list) 647 struct list_head *vc_list)
438{ 648{
439 int i; 649 int i;
@@ -445,9 +655,8 @@ static int __init process_ptload_program_headers_elf32(char *elfptr,
445 ehdr_ptr = (Elf32_Ehdr *)elfptr; 655 ehdr_ptr = (Elf32_Ehdr *)elfptr;
446 phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr)); /* PT_NOTE hdr */ 656 phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr)); /* PT_NOTE hdr */
447 657
448 /* First program header is PT_NOTE header. */ 658 /* Skip Elf header, program headers and Elf note segment. */
449 vmcore_off = elfsz + 659 vmcore_off = elfsz + elfnotes_sz;
450 phdr_ptr->p_memsz; /* Note sections */
451 660
452 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) { 661 for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
453 u64 paddr, start, end, size; 662 u64 paddr, start, end, size;
@@ -476,14 +685,14 @@ static int __init process_ptload_program_headers_elf32(char *elfptr,
476} 685}
477 686
478/* Sets offset fields of vmcore elements. */ 687/* Sets offset fields of vmcore elements. */
479static void __init set_vmcore_list_offsets(size_t elfsz, 688static void __init set_vmcore_list_offsets(size_t elfsz, size_t elfnotes_sz,
480 struct list_head *vc_list) 689 struct list_head *vc_list)
481{ 690{
482 loff_t vmcore_off; 691 loff_t vmcore_off;
483 struct vmcore *m; 692 struct vmcore *m;
484 693
485 /* Skip Elf header and program headers. */ 694 /* Skip Elf header, program headers and Elf note segment. */
486 vmcore_off = elfsz; 695 vmcore_off = elfsz + elfnotes_sz;
487 696
488 list_for_each_entry(m, vc_list, list) { 697 list_for_each_entry(m, vc_list, list) {
489 m->offset = vmcore_off; 698 m->offset = vmcore_off;
@@ -495,6 +704,8 @@ static void free_elfcorebuf(void)
495{ 704{
496 free_pages((unsigned long)elfcorebuf, get_order(elfcorebuf_sz_orig)); 705 free_pages((unsigned long)elfcorebuf, get_order(elfcorebuf_sz_orig));
497 elfcorebuf = NULL; 706 elfcorebuf = NULL;
707 vfree(elfnotes_buf);
708 elfnotes_buf = NULL;
498} 709}
499 710
500static int __init parse_crash_elf64_headers(void) 711static int __init parse_crash_elf64_headers(void)
@@ -538,14 +749,15 @@ static int __init parse_crash_elf64_headers(void)
538 goto fail; 749 goto fail;
539 750
540 /* Merge all PT_NOTE headers into one. */ 751 /* Merge all PT_NOTE headers into one. */
541 rc = merge_note_headers_elf64(elfcorebuf, &elfcorebuf_sz, &vmcore_list); 752 rc = merge_note_headers_elf64(elfcorebuf, &elfcorebuf_sz,
753 &elfnotes_buf, &elfnotes_sz);
542 if (rc) 754 if (rc)
543 goto fail; 755 goto fail;
544 rc = process_ptload_program_headers_elf64(elfcorebuf, elfcorebuf_sz, 756 rc = process_ptload_program_headers_elf64(elfcorebuf, elfcorebuf_sz,
545 &vmcore_list); 757 elfnotes_sz, &vmcore_list);
546 if (rc) 758 if (rc)
547 goto fail; 759 goto fail;
548 set_vmcore_list_offsets(elfcorebuf_sz, &vmcore_list); 760 set_vmcore_list_offsets(elfcorebuf_sz, elfnotes_sz, &vmcore_list);
549 return 0; 761 return 0;
550fail: 762fail:
551 free_elfcorebuf(); 763 free_elfcorebuf();
@@ -592,14 +804,15 @@ static int __init parse_crash_elf32_headers(void)
592 goto fail; 804 goto fail;
593 805
594 /* Merge all PT_NOTE headers into one. */ 806 /* Merge all PT_NOTE headers into one. */
595 rc = merge_note_headers_elf32(elfcorebuf, &elfcorebuf_sz, &vmcore_list); 807 rc = merge_note_headers_elf32(elfcorebuf, &elfcorebuf_sz,
808 &elfnotes_buf, &elfnotes_sz);
596 if (rc) 809 if (rc)
597 goto fail; 810 goto fail;
598 rc = process_ptload_program_headers_elf32(elfcorebuf, elfcorebuf_sz, 811 rc = process_ptload_program_headers_elf32(elfcorebuf, elfcorebuf_sz,
599 &vmcore_list); 812 elfnotes_sz, &vmcore_list);
600 if (rc) 813 if (rc)
601 goto fail; 814 goto fail;
602 set_vmcore_list_offsets(elfcorebuf_sz, &vmcore_list); 815 set_vmcore_list_offsets(elfcorebuf_sz, elfnotes_sz, &vmcore_list);
603 return 0; 816 return 0;
604fail: 817fail:
605 free_elfcorebuf(); 818 free_elfcorebuf();