[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