Blob Blame History Raw
From: Philipp Rudo <prudo@linux.ibm.com>
Subject: s390/kdump: Make elfcorehdr size calculation ABI compliant
Patch-mainline: v4.19-rc1
Git-commit: 263b0e480c9b0fda77a89f5d6375d8a39de5c166
References: bsc#1117953, LTC#171112

Description:  s390/kdump: Fix elfcorehdr size calculation
Symptom:      BUG_ON triggeres kernel panic in crash kernel.
Problem:      When the crash kernel allocates memory for the elfcorehdr, the
              assumed per-cpu memory is too small. The mis-calculation is
              usually countered by enough spare memory in the overhead
              (Elf_Ehdr, vmcoreinfo, etc.). However, with a growing overhead
              and/or huge cpu count the calculated size gets too small
              triggering the BUG_ON.
Solution:     Properly calculate the required size.
Reproduction: -

Upstream-Description:

              s390/kdump: Make elfcorehdr size calculation ABI compliant

              There are two ways to pass the vmcoreinfo to the crash kernel 1) via the
              os_info mechanism and 2) via the lowcore->vmcore_info field. In the Linux
              kernel only the second way is used. However, the first way is ABI for
              stand-alone kdump. So other OSes use it to pass additional debug info. Make
              the elfcorehdr size calculation aware of both possible ways.

              Fixes: 8cce437fbb5c ("s390/kdump: Fix elfcorehdr size calculation")
              Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
              Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com>
              Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>


Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 arch/s390/kernel/crash_dump.c |   28 +++++++++++-----------------
 1 file changed, 11 insertions(+), 17 deletions(-)

--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -477,26 +477,20 @@ static void *nt_vmcoreinfo(void *ptr)
 
 static size_t nt_vmcoreinfo_size(void)
 {
-	const char *name = "VMCOREINFO";
-	char nt_name[11];
-	Elf64_Nhdr note;
-	void *addr;
+	const char *name = VMCOREINFO_NOTE_NAME;
+	unsigned long size;
+	void *vmcoreinfo;
+
+	vmcoreinfo = os_info_old_entry(OS_INFO_VMCOREINFO, &size);
+	if (vmcoreinfo)
+		return nt_size_name(size, name);
 
-	if (copy_oldmem_kernel(&addr, &S390_lowcore.vmcore_info, sizeof(addr)))
+	vmcoreinfo = get_vmcoreinfo_old(&size);
+	if (!vmcoreinfo)
 		return 0;
 
-	if (copy_oldmem_kernel(&note, addr, sizeof(note)))
-		return 0;
-
-	memset(nt_name, 0, sizeof(nt_name));
-	if (copy_oldmem_kernel(nt_name, addr + sizeof(note),
-			       sizeof(nt_name) - 1))
-		return 0;
-
-	if (strcmp(nt_name, name) != 0)
-		return 0;
-
-	return nt_size_name(note.n_descsz, name);
+	kfree(vmcoreinfo);
+	return nt_size_name(size, name);
 }
 
 /*