[PATCH] makedumpfile: Fix several issues with reading ELF pages
Atsushi Kumagai
ats-kumagai at wm.jp.nec.com
Fri Mar 11 01:16:04 PST 2016
Hello Petr,
Thanks for your investigation and fixing the issue.
I'll merge this into v1.6.0.
Regards,
Atsushi Kumagai
>While adopting the algorithm for libkdumpfile, several corner cases
>were found by a test case:
>
> 1. If the last part of a page is not present in the ELF file, it
> should be replaced with zeroes. However, the check is incorrect.
>
> 2. If the beginning of a page is not present, following data is
> read from an incorrect file offset.
>
> 3. If the page is split among several segments, the current
> position in the buffer is not always taken into account.
>
>Case 1 is a simple typo/braino (writing bufptr instead of endp).
>
>To fix cases 2 and 3, it is best to update the paddr variable so that
>it always corresponds to the current read position in the buffer.
>
>I have tested the new code with a specially crafted ELF dump where one
>page had the following (artificial) layout:
>
> # PAGE RANGE STORED IN DATA
> --------------------------------------------------
> 1 0x000-0x007 nowhere fake zero
> 2 0x008-0x067 LOAD #1 read from file
> 3 0x068-0x06f nowhere fake zero
> 4 0x070-0x13f LOAD #2 read from file
> 5 0x140-0x147 LOAD #2 zero (memsz > filesz)
> 6 0x148-0xff7 LOAD #3 read from file
> 7 0xff8-0xfff nowhere fake zero
>
>Case 1 tests the conditional right after get_pt_load_extents().
>Case 2 tests file read after missing data.
>Case 3 tests the conditional from case 1 with non-zero buffer position.
>Case 5 tests the last conditional in the loop (p < endp).
>Case 6 tests exact match in get_pt_load_extents().
>Case 7 tests the final conditional after the loop.
>
>Signed-off-by: Petr Tesarik <ptesarik at suse.com>
>
>---
> makedumpfile.c | 18 ++++++++++++------
> 1 file changed, 12 insertions(+), 6 deletions(-)
>
>--- a/makedumpfile.c
>+++ b/makedumpfile.c
>@@ -656,14 +656,15 @@ readpage_elf(unsigned long long paddr, v
> p = bufptr;
> endp = p + info->page_size;
> while (p < endp) {
>- idx = closest_pt_load(paddr + (p - bufptr), endp - p);
>+ idx = closest_pt_load(paddr, endp - p);
> if (idx < 0)
> break;
>
> get_pt_load_extents(idx, &phys_start, &phys_end, &offset, &size);
>- if (phys_start > paddr + (p - bufptr)) {
>+ if (phys_start > paddr) {
> memset(p, 0, phys_start - paddr);
> p += phys_start - paddr;
>+ paddr = phys_start;
> }
>
> offset += paddr - phys_start;
>@@ -677,6 +678,7 @@ readpage_elf(unsigned long long paddr, v
> return FALSE;
> }
> p += size;
>+ paddr += size;
> }
> if (p < endp) {
> size = phys_end - paddr;
>@@ -684,6 +686,7 @@ readpage_elf(unsigned long long paddr, v
> size = endp - p;
> memset(p, 0, size);
> p += size;
>+ paddr += size;
> }
> }
>
>@@ -691,7 +694,7 @@ readpage_elf(unsigned long long paddr, v
> ERRMSG("Attempt to read non-existent page at 0x%llx.\n",
> paddr);
> return FALSE;
>- } else if (p < bufptr)
>+ } else if (p < endp)
> memset(p, 0, endp - p);
>
> return TRUE;
>@@ -708,14 +711,15 @@ readpage_elf_parallel(int fd_memory, uns
> p = bufptr;
> endp = p + info->page_size;
> while (p < endp) {
>- idx = closest_pt_load(paddr + (p - bufptr), endp - p);
>+ idx = closest_pt_load(paddr, endp - p);
> if (idx < 0)
> break;
>
> get_pt_load_extents(idx, &phys_start, &phys_end, &offset, &size);
>- if (phys_start > paddr + (p - bufptr)) {
>+ if (phys_start > paddr) {
> memset(p, 0, phys_start - paddr);
> p += phys_start - paddr;
>+ paddr = phys_start;
> }
>
> offset += paddr - phys_start;
>@@ -730,6 +734,7 @@ readpage_elf_parallel(int fd_memory, uns
> return FALSE;
> }
> p += size;
>+ paddr += size;
> }
> if (p < endp) {
> size = phys_end - paddr;
>@@ -737,6 +742,7 @@ readpage_elf_parallel(int fd_memory, uns
> size = endp - p;
> memset(p, 0, size);
> p += size;
>+ paddr += size;
> }
> }
>
>@@ -744,7 +750,7 @@ readpage_elf_parallel(int fd_memory, uns
> ERRMSG("Attempt to read non-existent page at 0x%llx.\n",
> paddr);
> return FALSE;
>- } else if (p < bufptr)
>+ } else if (p < endp)
> memset(p, 0, endp - p);
>
> return TRUE;
More information about the kexec
mailing list