[makedumpfile PATCH] Prevent data loss in last page of ELF core dumpfile

Eric DeVolder eric.devolder at oracle.com
Wed Jul 5 07:11:29 PDT 2017


On 07/05/2017 03:34 AM, Atsushi Kumagai wrote:
> Hello Eric,
>
> Good catch, thanks for your investigation.
> Please see the comment below.
>
>> When generating an ELF core dump file, if a segment/section size
>> is not an integral of PAGE_SIZE, then the corresponding generated
>> segment/section is erroneously truncated to a PAGE_SIZE integral.
>> Thus a small loss of data up to PAGE_SIZE-1 bytes can occur.
>>
>> In the function write_elf_pages_cyclic(), two variables memsz and
>> filesz track the sizes. This patch provides the missing update to
>> filesz for one particular condition, in a fashion consistent with
>> the update to memsz in this condition.
>>
>> This patch corrects the test case described here.
>>
>> I have an existing ELF vmcore dumpfile and run it through
>> makedumpfile again, as such:
>>
>> % makedumpfile -E -x vmlinux vmcore newvmcore
>> % objdump --all-headers vmcore > before.txt
>> % objdump --all-headers newvmcore > after.txt
>>
>>From crash, here is a description of the original vmcore:
>>
>>      KERNEL: vmlinux
>>    DUMPFILE: vmcore
>>        CPUS: 4
>>        DATE: Thu Jan  7 07:49:10 2016
>>      UPTIME: 00:00:22
>> LOAD AVERAGE: 0.00, 0.00, 0.00
>>       TASKS: 77
>>    NODENAME: mini-amd64
>>     RELEASE: 4.2.0-ns.gen.amd64.1
>>     VERSION: #1 SMP Wed Oct 28 16:32:12 CET 2015
>>     MACHINE: x86_64  (2194 Mhz)
>>      MEMORY: 4 GB
>>       PANIC: "sysrq: SysRq : Trigger a crash"
>>         PID: 96
>>     COMMAND: "bash"
>>        TASK: ffff88017a4c9e00  [THREAD_INFO: ffff88017a198000]
>>         CPU: 3
>>       STATE: TASK_RUNNING (SYSRQ)
>>
>> In essence, no re-filtering has occured and I expect to see a very similar
>> ELF dump file to the original.  And for the most part, the files are similar,
>> but I do observe some differences.
>>
>> The contents of before.txt are:
>>
>> == before.txt ========================================================
>> vmcore:     file format elf64-x86-64
>> vmcore
>> architecture: i386:x86-64, flags 0x00000000:
>>
>> start address 0x0000000000000000
>>
>> Program Header:
>>    NOTE off    0x0000000000001000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**0
>>         filesz 0x0000000000000c6c memsz 0x0000000000000c6c flags ---
>>    LOAD off    0x0000000000002000 vaddr 0xffffffff81000000 paddr 0x0000000001000000 align 2**0
>>         filesz 0x0000000000829000 memsz 0x0000000000829000 flags rwx
>>    LOAD off    0x000000000082b000 vaddr 0xffff880000001000 paddr 0x0000000000001000 align 2**0
>>         filesz 0x000000000009ec00 memsz 0x000000000009ec00 flags rwx
>>    LOAD off    0x00000000008ca000 vaddr 0xffff880000100000 paddr 0x0000000000100000 align 2**0
>>         filesz 0x0000000003f00000 memsz 0x0000000003f00000 flags rwx
>>    LOAD off    0x00000000047ca000 vaddr 0xffff880014000000 paddr 0x0000000014000000 align 2**0
>>         filesz 0x000000006bfdf000 memsz 0x000000006bfdf000 flags rwx
>>    LOAD off    0x00000000707a9000 vaddr 0xffff880100000000 paddr 0x0000000100000000 align 2**0
>>         filesz 0x0000000080000000 memsz 0x0000000080000000 flags rwx
>>
>> Sections:
>> Idx Name          Size      VMA               LMA               File off  Algn
>>  0 note0         00000c6c  0000000000000000  0000000000000000  00001000  2**0
>>                  CONTENTS, READONLY
>>  1 .reg/0        000000d8  0000000000000000  0000000000000000  00001084  2**2
>>                  CONTENTS
>>  2 .reg          000000d8  0000000000000000  0000000000000000  00001084  2**2
>>                  CONTENTS
>>  3 .reg/0        000000d8  0000000000000000  0000000000000000  000011e8  2**2
>>                  CONTENTS
>>  4 .reg/0        000000d8  0000000000000000  0000000000000000  0000134c  2**2
>>                  CONTENTS
>>  5 .reg/96       000000d8  0000000000000000  0000000000000000  000014b0  2**2
>>                  CONTENTS
>>  6 load1         00829000  ffffffff81000000  0000000001000000  00002000  2**0
>>                  CONTENTS, ALLOC, LOAD, CODE
>>  7 load2         0009ec00  ffff880000001000  0000000000001000  0082b000  2**0
>>                  CONTENTS, ALLOC, LOAD, CODE
>>  8 load3         03f00000  ffff880000100000  0000000000100000  008ca000  2**0
>>                  CONTENTS, ALLOC, LOAD, CODE
>>  9 load4         6bfdf000  ffff880014000000  0000000014000000  047ca000  2**0
>>                  CONTENTS, ALLOC, LOAD, CODE
>> 10 load5         80000000  ffff880100000000  0000000100000000  707a9000  2**0
>>                  CONTENTS, ALLOC, LOAD, CODE
>> SYMBOL TABLE:
>> no symbols
>>
>> == before.txt ========================================================
>>
>> And the contents of after.txt:
>>
>> == after.txt =========================================================
>> newvmcore:  file format elf64-x86-64
>> newvmcore:
>> architecture: i386:x86-64, flags 0x00000000:
>>
>> start address 0x0000000000000000
>>
>> Program Header:
>>    NOTE off    0x0000000000000190 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**0
>>         filesz 0x0000000000000c6c memsz 0x0000000000000c6c flags ---
>>    LOAD off    0x0000000000000dfc vaddr 0xffffffff81000000 paddr 0x0000000001000000 align 2**0
>>         filesz 0x0000000000829000 memsz 0x0000000000829000 flags rwx
>>    LOAD off    0x0000000000829dfc vaddr 0xffff880000001000 paddr 0x0000000000001000 align 2**0
>>         filesz 0x000000000009e000 memsz 0x000000000009ec00 flags rwx
>>    LOAD off    0x00000000008c7dfc vaddr 0xffff880000100000 paddr 0x0000000000100000 align 2**0
>>         filesz 0x0000000003f00000 memsz 0x0000000003f00000 flags rwx
>>    LOAD off    0x00000000047c7dfc vaddr 0xffff880014000000 paddr 0x0000000014000000 align 2**0
>>         filesz 0x000000006bfdf000 memsz 0x000000006bfdf000 flags rwx
>>    LOAD off    0x00000000707a6dfc vaddr 0xffff880100000000 paddr 0x0000000100000000 align 2**0
>>         filesz 0x0000000080000000 memsz 0x0000000080000000 flags rwx
>>
>> Sections:
>> Idx Name          Size      VMA               LMA               File off  Algn
>>  0 note0         00000c6c  0000000000000000  0000000000000000  00000190  2**0
>>                  CONTENTS, READONLY
>>  1 .reg/0        000000d8  0000000000000000  0000000000000000  00000214  2**2
>>                  CONTENTS
>>  2 .reg          000000d8  0000000000000000  0000000000000000  00000214  2**2
>>                  CONTENTS
>>  3 .reg/0        000000d8  0000000000000000  0000000000000000  00000378  2**2
>>                  CONTENTS
>>  4 .reg/0        000000d8  0000000000000000  0000000000000000  000004dc  2**2
>>                  CONTENTS
>>  5 .reg/96       000000d8  0000000000000000  0000000000000000  00000640  2**2
>>                  CONTENTS
>>  6 load1         00829000  ffffffff81000000  0000000001000000  00000dfc  2**0
>>                  CONTENTS, ALLOC, LOAD, CODE
>>  7 load2a        0009e000  ffff880000001000  0000000000001000  00829dfc  2**0
>>                  CONTENTS, ALLOC, LOAD, CODE
>>  8 load2b        00000000  ffff88000009f000  000000000009f000  008c7dfc  2**0
>>                  ALLOC, CODE
>>  9 load3         03f00000  ffff880000100000  0000000000100000  008c7dfc  2**0
>>                  CONTENTS, ALLOC, LOAD, CODE
>> 10 load4         6bfdf000  ffff880014000000  0000000014000000  047c7dfc  2**0
>>                  CONTENTS, ALLOC, LOAD, CODE
>> 11 load5         80000000  ffff880100000000  0000000100000000  707a6dfc  2**0
>>                  CONTENTS, ALLOC, LOAD, CODE
>> == after.txt =========================================================
>>
>> If we ignore the file offset differences, one can see that something has
>> happened to "load2".
>>
>> The original vmcore "load2" looks like:
>>
>> Program Header:
>>    LOAD off    0x000000000082b000 vaddr 0xffff880000001000 paddr 0x0000000000001000 align 2**0
>>         filesz 0x000000000009ec00 memsz 0x000000000009ec00 flags rwx
>> Sections:
>>  7 load2         0009ec00  ffff880000001000  0000000000001000  0082b000  2**0
>>                  CONTENTS, ALLOC, LOAD, CODE
>>
>> It was split into these when passed through makedumpfile:
>>
>> Program Header:
>>    LOAD off    0x0000000000829dfc vaddr 0xffff880000001000 paddr 0x0000000000001000 align 2**0
>>         filesz 0x000000000009e000 memsz 0x000000000009ec00 flags rwx
>> Sections:
>>  7 load2a        0009e000  ffff880000001000  0000000000001000  00829dfc  2**0
>>                  CONTENTS, ALLOC, LOAD, CODE
>>  8 load2b        00000000  ffff88000009f000  000000000009f000  008c7dfc  2**0
>>                  ALLOC, CODE
>>
>> In doing so, makedumpfile truncated the size of "load2a" 0009e000 by 0xc00
>> bytes compared to original vmcore "load2" 0009ec00. This appears to be a
>> loss of data, and likely bug.
>>
>> In addition, makedumpfile also generated a new zero-length section (and no
>> corresponding program header, thankfully) of what would appear to be the page
>> address following the end of "load2a". This seems to be un-necessary, and
>> perhaps a likely bug, though harmless for this example.
>>
>> With the patch applied, the correct segment and section are generated (and
>> no extraneous section), and the newly generated vmcore loads within 'crash'.
>>
>> Signed-off-by: Eric DeVolder <eric.devolder at oracle.com>
>> ---
>> ---
>> makedumpfile.c | 7 +++++--
>> 1 file changed, 5 insertions(+), 2 deletions(-)
>>
>> diff --git a/makedumpfile.c b/makedumpfile.c
>> index e69b6df..94359ac 100644
>> --- a/makedumpfile.c
>> +++ b/makedumpfile.c
>> @@ -7326,10 +7326,13 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page)
>> 			for (pfn = MAX(pfn_start, cycle.start_pfn); pfn < cycle.end_pfn; pfn++) {
>> 				if (!is_dumpable(info->bitmap2, pfn, &cycle)) {
>> 					num_excluded++;
>> -					if ((pfn == pfn_end - 1) && frac_tail)
>> +					if ((pfn == pfn_end - 1) && frac_tail) {
>> 						memsz += frac_tail;
>> -					else
>> +						filesz += frac_tail;
>> +					} else {
>> 						memsz += page_size;
>> +						filesz += page_size;
>> +                    }
>
> As "!is_dumpable()" indicates, this block is for page filtering.
> If a page is excluded, page_size shouldn't be added to filesz since
> the page is not included in the file.
>
> So I don't think this approach is proper, but I don't have a good
> idea for now. It seems that a frac_tail page can be judged as
> "not dumpable" erroneously even without filtering, I suspect it's
> the root cause of your problem.
>
>
> Thanks,
> Atsushi Kumagai
>

Yes, I that does make more sense, I'll look into is_dumpable() more  
closely for the frac_tail case.

Thanks!
eric




More information about the kexec mailing list