s390/kdump: Add final note
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>
Thu, 23 Mar 2017 20:02:54 +0000 (21:02 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 28 Mar 2017 14:54:31 +0000 (16:54 +0200)
Since linux v3.14 with commit 38dfac843cb6d7be1 ("vmcore: prevent PT_NOTE
p_memsz overflow during header update") on s390 we get the following
message in the kdump kernel:

  Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x6b6b6b6b,
  n_descsz=0x6b6b6b6b

The reason for this is that we don't create a final zero note in
the ELF header which the proc/vmcore code uses to find out the end
of the notes section (see also kernel/kexec_core.c:final_note()).

It still worked on s390 by chance because we (most of the time?) have the
byte pattern 0x6b6b6b6b after the notes section which also makes the notes
parsing code stop in update_note_header_size_elf64() because 0x6b6b6b6b is
interpreded as note size:

  if ((real_sz + sz) > max_sz) {
          pr_warn("Warning: Exceeded p_memsz, dropping P ...);
          break;
  }

So fix this and add the missing final note to the ELF header.
We don't have to adjust the memory size for ELF header ("alloc_size")
because the new ELF note still fits into the 0x1000 base memory.

Cc: stable@vger.kernel.org # v4.4+
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/kernel/crash_dump.c

index dd1d5c62c374b70919a7b7c727291977e0c90cf2..d628afc267087cc2a01044a0113a1024846951c7 100644 (file)
@@ -428,6 +428,20 @@ static void *nt_vmcoreinfo(void *ptr)
        return nt_init_name(ptr, 0, vmcoreinfo, size, "VMCOREINFO");
 }
 
+/*
+ * Initialize final note (needed for /proc/vmcore code)
+ */
+static void *nt_final(void *ptr)
+{
+       Elf64_Nhdr *note;
+
+       note = (Elf64_Nhdr *) ptr;
+       note->n_namesz = 0;
+       note->n_descsz = 0;
+       note->n_type = 0;
+       return PTR_ADD(ptr, sizeof(Elf64_Nhdr));
+}
+
 /*
  * Initialize ELF header (new kernel)
  */
@@ -515,6 +529,7 @@ static void *notes_init(Elf64_Phdr *phdr, void *ptr, u64 notes_offset)
                if (sa->prefix != 0)
                        ptr = fill_cpu_elf_notes(ptr, cpu++, sa);
        ptr = nt_vmcoreinfo(ptr);
+       ptr = nt_final(ptr);
        memset(phdr, 0, sizeof(*phdr));
        phdr->p_type = PT_NOTE;
        phdr->p_offset = notes_offset;