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 <ptesa...@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;

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to