Accepting request 562833 from home:ptesarik:branches:Kernel:kdump
- makedumpfile-__cpu_online_mask-symbol.patch: Support symbol __cpu_online_mask (FATE#323473, bsc#1070291). - makedumpfile-vtop4_x86_64_pagetable.patch: Introduce vtop4_x86_64_pagetable (FATE#323473, bsc#1070291). - makedumpfile-fix-KASLR-for-sadump.patch: Fix a KASLR problem of sadump (FATE#323473, bsc#1070291). - makedumpfile-fix-KASLR-for-sadump-while-kdump.patch: sadump: Fix a KASLR problem of sadump while kdump is working (FATE#323473, bsc#1070291). OBS-URL: https://build.opensuse.org/request/show/562833 OBS-URL: https://build.opensuse.org/package/show/Kernel:kdump/makedumpfile?expand=0&rev=113
This commit is contained in:
parent
e4d35d5e02
commit
4877ee4b98
@ -1,8 +1,9 @@
|
||||
From: Pratyush Anand <panand@redhat.com>
|
||||
Date: Thu, 17 Aug 2017 12:47:13 +0900
|
||||
Subject: [PATCH v2] Fix SECTION_MAP_MASK for kernel >= v.13
|
||||
Patch-mainline: yes
|
||||
Subject: Fix SECTION_MAP_MASK for kernel >= v.13
|
||||
References: bnc#1066811, bsc#1067703
|
||||
Upstream: merged
|
||||
Git-commit: a02f5f078ce635dd1633dab70869306b0a62e2e2
|
||||
|
||||
* Required for kernel 4.13
|
||||
* Required for SLE15 kernel due to backport of 2d070eab2e82 => 4.12
|
||||
|
63
makedumpfile-__cpu_online_mask-symbol.patch
Normal file
63
makedumpfile-__cpu_online_mask-symbol.patch
Normal file
@ -0,0 +1,63 @@
|
||||
From: Takao Indoh <indou.takao@jp.fujitsu.com>
|
||||
Date: Thu, 26 Oct 2017 20:32:48 +0900
|
||||
Subject: Support symbol __cpu_online_mask
|
||||
References: FATE#323473, bsc#1070291
|
||||
Upstream: merged
|
||||
Git-commit: d6d5b443c82471818d43cb87c9280a0252e763e7
|
||||
|
||||
In the upstream kernel, by commit 5aec01b83 cpu_online_mask was replaced
|
||||
with macros and new variables __cpu_online_mask was added instead of it.
|
||||
Sadump uses cpu_online_mask to check the cpu was online or not,
|
||||
therefore it also need __cpu_online_mask symbol for this in the latest
|
||||
kernel.
|
||||
|
||||
Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
|
||||
Signed-off-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
|
||||
Acked-by: Petr Tesarik <ptesarik@suse.com>
|
||||
|
||||
---
|
||||
makedumpfile.c | 9 +++++++--
|
||||
makedumpfile.h | 1 +
|
||||
sadump_info.c | 3 ++-
|
||||
3 files changed, 10 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/makedumpfile.c
|
||||
+++ b/makedumpfile.c
|
||||
@@ -1519,8 +1519,13 @@ get_symbol_info(void)
|
||||
SYMBOL_INIT(__per_cpu_load, "__per_cpu_load");
|
||||
SYMBOL_INIT(__per_cpu_offset, "__per_cpu_offset");
|
||||
SYMBOL_INIT(cpu_online_mask, "cpu_online_mask");
|
||||
- if (SYMBOL(cpu_online_mask) == NOT_FOUND_SYMBOL)
|
||||
- SYMBOL_INIT(cpu_online_mask, "cpu_online_map");
|
||||
+ SYMBOL_INIT(__cpu_online_mask, "__cpu_online_mask");
|
||||
+ if (SYMBOL(cpu_online_mask) == NOT_FOUND_SYMBOL) {
|
||||
+ if (SYMBOL(__cpu_online_mask) == NOT_FOUND_SYMBOL)
|
||||
+ SYMBOL_INIT(cpu_online_mask, "cpu_online_map");
|
||||
+ else
|
||||
+ SYMBOL_INIT(cpu_online_mask, "__cpu_online_mask");
|
||||
+ }
|
||||
SYMBOL_INIT(kexec_crash_image, "kexec_crash_image");
|
||||
SYMBOL_INIT(node_remap_start_vaddr, "node_remap_start_vaddr");
|
||||
SYMBOL_INIT(node_remap_end_vaddr, "node_remap_end_vaddr");
|
||||
--- a/makedumpfile.h
|
||||
+++ b/makedumpfile.h
|
||||
@@ -1590,6 +1590,7 @@ struct symbol_table {
|
||||
unsigned long long __per_cpu_offset;
|
||||
unsigned long long __per_cpu_load;
|
||||
unsigned long long cpu_online_mask;
|
||||
+ unsigned long long __cpu_online_mask;
|
||||
unsigned long long kexec_crash_image;
|
||||
|
||||
/*
|
||||
--- a/sadump_info.c
|
||||
+++ b/sadump_info.c
|
||||
@@ -953,7 +953,8 @@ cpu_online_mask_init(void)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
- if (SIZE(cpumask) == NOT_FOUND_STRUCTURE)
|
||||
+ if ((SIZE(cpumask) == NOT_FOUND_STRUCTURE) ||
|
||||
+ (SYMBOL(__cpu_online_mask) != NOT_FOUND_SYMBOL))
|
||||
cpu_online_mask_addr = SYMBOL(cpu_online_mask);
|
||||
|
||||
else {
|
@ -1,11 +1,11 @@
|
||||
From dc28bfc3213960b549bcc70f0d5379a6222d2c60 Mon Sep 17 00:00:00 2001
|
||||
From: Bhupesh Sharma <bhsharma@redhat.com>
|
||||
Date: Wed, 13 Sep 2017 05:04:00 +0900
|
||||
Subject: [PATCH] [PATCH v2] book3s/ppc64: Lower the max real address to 53
|
||||
Subject: book3s/ppc64: Lower the max real address to 53
|
||||
bits for kernels >= v4.11
|
||||
|
||||
Patch-mainline: yes
|
||||
References: bsc#1067703
|
||||
Upstream: merged
|
||||
Git-commit: dc28bfc3213960b549bcc70f0d5379a6222d2c60
|
||||
|
||||
* Required for kernel 4.11
|
||||
|
||||
Kernel commit 2f18d533757da3899f4bedab0b2c051b080079dc lowered the
|
||||
|
353
makedumpfile-fix-KASLR-for-sadump-while-kdump.patch
Normal file
353
makedumpfile-fix-KASLR-for-sadump-while-kdump.patch
Normal file
@ -0,0 +1,353 @@
|
||||
From: Takao Indoh <indou.takao@jp.fujitsu.com>
|
||||
Date: Thu, 26 Oct 2017 20:33:01 +0900
|
||||
Subject: sadump: Fix a KASLR problem of sadump while kdump is working
|
||||
References: FATE#323473, bsc#1070291
|
||||
Upstream: merged
|
||||
Git-commit: 09288f2058c8066a2729588ec668eed3e1140028
|
||||
|
||||
In the calc_kaslr_offset(), kaslr_offset and phys_base are calculated
|
||||
using IDTR and CR3, but this solution does not work in the following
|
||||
cases.
|
||||
|
||||
1) If the dump is captured on early stage of kernel boot, IDTR points
|
||||
early IDT table(early_idts) instead of normal IDT(idt_table).
|
||||
2) If the dump is captured whle kdump is working, IDTR points IDT table
|
||||
of 2nd kernel, not 1st kernel.
|
||||
|
||||
This patch fixes the case 2). Current implementation does not support
|
||||
the case 1), need enhancement in the future. This patch gets kernel boot
|
||||
parameter from "saved_command_line" and check if "elfcorehdr=" is
|
||||
included in the parameter. If it's included, we are in the 2nd kernel.
|
||||
Retrieve vmcoreinfo from address of "elfcorehdr=" and get kaslr_offset
|
||||
and phys_base from vmcoreinfo.
|
||||
|
||||
Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
|
||||
Acked-by: Petr Tesarik <ptesarik@suse.com>
|
||||
|
||||
---
|
||||
makedumpfile.c | 1
|
||||
makedumpfile.h | 1
|
||||
sadump_info.c | 271 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 273 insertions(+)
|
||||
|
||||
--- a/makedumpfile.c
|
||||
+++ b/makedumpfile.c
|
||||
@@ -1556,6 +1556,7 @@ get_symbol_info(void)
|
||||
|
||||
SYMBOL_INIT(divide_error, "divide_error");
|
||||
SYMBOL_INIT(idt_table, "idt_table");
|
||||
+ SYMBOL_INIT(saved_command_line, "saved_command_line");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
--- a/makedumpfile.h
|
||||
+++ b/makedumpfile.h
|
||||
@@ -1596,6 +1596,7 @@ struct symbol_table {
|
||||
unsigned long long kexec_crash_image;
|
||||
unsigned long long divide_error;
|
||||
unsigned long long idt_table;
|
||||
+ unsigned long long saved_command_line;
|
||||
|
||||
/*
|
||||
* symbols on ppc64 arch
|
||||
--- a/sadump_info.c
|
||||
+++ b/sadump_info.c
|
||||
@@ -1059,6 +1059,241 @@ get_vec0_addr(ulong idtr)
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Parse a string of [size[KMG]@]offset[KMG]
|
||||
+ * Import from Linux kernel(lib/cmdline.c)
|
||||
+ */
|
||||
+static ulong memparse(char *ptr, char **retptr)
|
||||
+{
|
||||
+ char *endptr;
|
||||
+
|
||||
+ unsigned long long ret = strtoull(ptr, &endptr, 0);
|
||||
+
|
||||
+ switch (*endptr) {
|
||||
+ case 'E':
|
||||
+ case 'e':
|
||||
+ ret <<= 10;
|
||||
+ case 'P':
|
||||
+ case 'p':
|
||||
+ ret <<= 10;
|
||||
+ case 'T':
|
||||
+ case 't':
|
||||
+ ret <<= 10;
|
||||
+ case 'G':
|
||||
+ case 'g':
|
||||
+ ret <<= 10;
|
||||
+ case 'M':
|
||||
+ case 'm':
|
||||
+ ret <<= 10;
|
||||
+ case 'K':
|
||||
+ case 'k':
|
||||
+ ret <<= 10;
|
||||
+ endptr++;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (retptr)
|
||||
+ *retptr = endptr;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Find "elfcorehdr=" in the boot parameter of kernel and return the address
|
||||
+ * of elfcorehdr.
|
||||
+ */
|
||||
+static ulong
|
||||
+get_elfcorehdr(ulong cr3)
|
||||
+{
|
||||
+ char cmdline[BUFSIZE], *ptr;
|
||||
+ ulong cmdline_vaddr;
|
||||
+ ulong cmdline_paddr;
|
||||
+ ulong buf_vaddr, buf_paddr;
|
||||
+ char *end;
|
||||
+ ulong elfcorehdr_addr = 0, elfcorehdr_size = 0;
|
||||
+
|
||||
+ if (SYMBOL(saved_command_line) == NOT_FOUND_SYMBOL) {
|
||||
+ ERRMSG("Can't get the symbol of saved_command_line.\n");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ cmdline_vaddr = SYMBOL(saved_command_line);
|
||||
+ if ((cmdline_paddr = vtop4_x86_64_pagetable(cmdline_vaddr, cr3)) == NOT_PADDR)
|
||||
+ return 0;
|
||||
+
|
||||
+ DEBUG_MSG("sadump: cmdline vaddr: %lx\n", cmdline_vaddr);
|
||||
+ DEBUG_MSG("sadump: cmdline paddr: %lx\n", cmdline_paddr);
|
||||
+
|
||||
+ if (!readmem(PADDR, cmdline_paddr, &buf_vaddr, sizeof(ulong)))
|
||||
+ return 0;
|
||||
+
|
||||
+ if ((buf_paddr = vtop4_x86_64_pagetable(buf_vaddr, cr3)) == NOT_PADDR)
|
||||
+ return 0;
|
||||
+
|
||||
+ DEBUG_MSG("sadump: cmdline buf vaddr: %lx\n", buf_vaddr);
|
||||
+ DEBUG_MSG("sadump: cmdline buf paddr: %lx\n", buf_paddr);
|
||||
+
|
||||
+ memset(cmdline, 0, BUFSIZE);
|
||||
+ if (!readmem(PADDR, buf_paddr, cmdline, BUFSIZE))
|
||||
+ return 0;
|
||||
+
|
||||
+ ptr = strstr(cmdline, "elfcorehdr=");
|
||||
+ if (!ptr)
|
||||
+ return 0;
|
||||
+
|
||||
+ DEBUG_MSG("sadump: 2nd kernel detected.\n");
|
||||
+
|
||||
+ ptr += strlen("elfcorehdr=");
|
||||
+ elfcorehdr_addr = memparse(ptr, &end);
|
||||
+ if (*end == '@') {
|
||||
+ elfcorehdr_size = elfcorehdr_addr;
|
||||
+ elfcorehdr_addr = memparse(end + 1, &end);
|
||||
+ }
|
||||
+
|
||||
+ DEBUG_MSG("sadump: elfcorehdr_addr: %lx\n", elfcorehdr_addr);
|
||||
+ DEBUG_MSG("sadump: elfcorehdr_size: %lx\n", elfcorehdr_size);
|
||||
+
|
||||
+ return elfcorehdr_addr;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Get vmcoreinfo from elfcorehdr.
|
||||
+ * Some codes are imported from Linux kernel(fs/proc/vmcore.c)
|
||||
+ */
|
||||
+static int
|
||||
+get_vmcoreinfo_in_kdump_kernel(ulong elfcorehdr, ulong *addr, int *len)
|
||||
+{
|
||||
+ unsigned char e_ident[EI_NIDENT];
|
||||
+ Elf64_Ehdr ehdr;
|
||||
+ Elf64_Phdr phdr;
|
||||
+ Elf64_Nhdr nhdr;
|
||||
+ ulong ptr;
|
||||
+ ulong nhdr_offset = 0;
|
||||
+ int i;
|
||||
+
|
||||
+ if (!readmem(PADDR, elfcorehdr, e_ident, EI_NIDENT))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (e_ident[EI_CLASS] != ELFCLASS64) {
|
||||
+ ERRMSG("Only ELFCLASS64 is supportd\n");
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ if (!readmem(PADDR, elfcorehdr, &ehdr, sizeof(ehdr)))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ /* Sanity Check */
|
||||
+ if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
|
||||
+ (ehdr.e_type != ET_CORE) ||
|
||||
+ ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
|
||||
+ ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
|
||||
+ ehdr.e_version != EV_CURRENT ||
|
||||
+ ehdr.e_ehsize != sizeof(Elf64_Ehdr) ||
|
||||
+ ehdr.e_phentsize != sizeof(Elf64_Phdr) ||
|
||||
+ ehdr.e_phnum == 0) {
|
||||
+ ERRMSG("Invalid elf header\n");
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ ptr = elfcorehdr + ehdr.e_phoff;
|
||||
+ for (i = 0; i < ehdr.e_phnum; i++) {
|
||||
+ ulong offset;
|
||||
+ char name[16];
|
||||
+
|
||||
+ if (!readmem(PADDR, ptr, &phdr, sizeof(phdr)))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ ptr += sizeof(phdr);
|
||||
+ if (phdr.p_type != PT_NOTE)
|
||||
+ continue;
|
||||
+
|
||||
+ offset = phdr.p_offset;
|
||||
+ if (!readmem(PADDR, offset, &nhdr, sizeof(nhdr)))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ offset += divideup(sizeof(Elf64_Nhdr), sizeof(Elf64_Word))*
|
||||
+ sizeof(Elf64_Word);
|
||||
+ memset(name, 0, sizeof(name));
|
||||
+ if (!readmem(PADDR, offset, name, sizeof(name)))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if(!strcmp(name, "VMCOREINFO")) {
|
||||
+ nhdr_offset = offset;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!nhdr_offset)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ *addr = nhdr_offset +
|
||||
+ divideup(nhdr.n_namesz, sizeof(Elf64_Word))*
|
||||
+ sizeof(Elf64_Word);
|
||||
+ *len = nhdr.n_descsz;
|
||||
+
|
||||
+ DEBUG_MSG("sadump: vmcoreinfo addr: %lx\n", *addr);
|
||||
+ DEBUG_MSG("sadump: vmcoreinfo len: %d\n", *len);
|
||||
+
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Check if current kaslr_offset/phys_base is for 1st kernel or 2nd kernel.
|
||||
+ * If we are in 2nd kernel, get kaslr_offset/phys_base from vmcoreinfo.
|
||||
+ *
|
||||
+ * 1. Get command line and try to retrieve "elfcorehdr=" boot parameter
|
||||
+ * 2. If "elfcorehdr=" is not found in command line, we are in 1st kernel.
|
||||
+ * There is nothing to do.
|
||||
+ * 3. If "elfcorehdr=" is found, we are in 2nd kernel. Find vmcoreinfo
|
||||
+ * using "elfcorehdr=" and retrieve kaslr_offset/phys_base from vmcoreinfo.
|
||||
+ */
|
||||
+int
|
||||
+get_kaslr_offset_from_vmcoreinfo(ulong cr3, ulong *kaslr_offset,
|
||||
+ ulong *phys_base)
|
||||
+{
|
||||
+ ulong elfcorehdr_addr = 0;
|
||||
+ ulong vmcoreinfo_addr;
|
||||
+ int vmcoreinfo_len;
|
||||
+ char *buf, *pos;
|
||||
+ int ret = FALSE;
|
||||
+
|
||||
+ elfcorehdr_addr = get_elfcorehdr(cr3);
|
||||
+ if (!elfcorehdr_addr)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (!get_vmcoreinfo_in_kdump_kernel(elfcorehdr_addr, &vmcoreinfo_addr,
|
||||
+ &vmcoreinfo_len))
|
||||
+ return FALSE;
|
||||
+
|
||||
+ if (!vmcoreinfo_len)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ DEBUG_MSG("sadump: Find vmcoreinfo in kdump memory\n");
|
||||
+
|
||||
+ if (!(buf = malloc(vmcoreinfo_len))) {
|
||||
+ ERRMSG("Can't allocate vmcoreinfo buffer.\n");
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ if (!readmem(PADDR, vmcoreinfo_addr, buf, vmcoreinfo_len))
|
||||
+ goto finish;
|
||||
+
|
||||
+ pos = strstr(buf, STR_NUMBER("phys_base"));
|
||||
+ if (!pos)
|
||||
+ goto finish;
|
||||
+ *phys_base = strtoull(pos + strlen(STR_NUMBER("phys_base")), NULL, 0);
|
||||
+
|
||||
+ pos = strstr(buf, STR_KERNELOFFSET);
|
||||
+ if (!pos)
|
||||
+ goto finish;
|
||||
+ *kaslr_offset = strtoull(pos + strlen(STR_KERNELOFFSET), NULL, 16);
|
||||
+ ret = TRUE;
|
||||
+
|
||||
+finish:
|
||||
+ free(buf);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* Calculate kaslr_offset and phys_base
|
||||
*
|
||||
* kaslr_offset:
|
||||
@@ -1106,6 +1341,26 @@ get_vec0_addr(ulong idtr)
|
||||
*
|
||||
* Note that the address (A) cannot be used instead of (E) because (A) is
|
||||
* not direct map address, it's a fixed map address.
|
||||
+ *
|
||||
+ * This solution works in most every case, but does not work in the
|
||||
+ * following case.
|
||||
+ *
|
||||
+ * 1) If the dump is captured on early stage of kernel boot, IDTR points
|
||||
+ * early IDT table(early_idts) instead of normal IDT(idt_table).
|
||||
+ * 2) If the dump is captured whle kdump is working, IDTR points
|
||||
+ * IDT table of 2nd kernel, not 1st kernel.
|
||||
+ *
|
||||
+ * Current implementation does not support the case 1), need
|
||||
+ * enhancement in the future. For the case 2), get kaslr_offset and
|
||||
+ * phys_base as follows.
|
||||
+ *
|
||||
+ * 1) Get kaslr_offset and phys_base using the above solution.
|
||||
+ * 2) Get kernel boot parameter from "saved_command_line"
|
||||
+ * 3) If "elfcorehdr=" is not included in boot parameter, we are in the
|
||||
+ * first kernel, nothing to do any more.
|
||||
+ * 4) If "elfcorehdr=" is included in boot parameter, we are in the 2nd
|
||||
+ * kernel. Retrieve vmcoreinfo from address of "elfcorehdr=" and
|
||||
+ * get kaslr_offset and phys_base from vmcoreinfo.
|
||||
*/
|
||||
int
|
||||
calc_kaslr_offset(void)
|
||||
@@ -1116,6 +1371,7 @@ calc_kaslr_offset(void)
|
||||
int apicid;
|
||||
unsigned long divide_error_vmcore, divide_error_vmlinux;
|
||||
unsigned long kaslr_offset, phys_base;
|
||||
+ unsigned long kaslr_offset_kdump, phys_base_kdump;
|
||||
|
||||
memset(&zero, 0, sizeof(zero));
|
||||
for (apicid = 0; apicid < sh->nr_cpus; ++apicid) {
|
||||
@@ -1161,6 +1417,21 @@ calc_kaslr_offset(void)
|
||||
if (!get_symbol_info())
|
||||
return FALSE;
|
||||
|
||||
+ /*
|
||||
+ * Check if current kaslr_offset/phys_base is for 1st kernel or 2nd
|
||||
+ * kernel. If we are in 2nd kernel, get kaslr_offset/phys_base
|
||||
+ * from vmcoreinfo
|
||||
+ */
|
||||
+ if (get_kaslr_offset_from_vmcoreinfo(cr3, &kaslr_offset_kdump,
|
||||
+ &phys_base_kdump)) {
|
||||
+ info->kaslr_offset = kaslr_offset_kdump;
|
||||
+ info->phys_base = phys_base_kdump;
|
||||
+
|
||||
+ /* Reload symbol */
|
||||
+ if (!get_symbol_info())
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
DEBUG_MSG("sadump: kaslr_offset=%lx\n", info->kaslr_offset);
|
||||
DEBUG_MSG("sadump: phys_base=%lx\n", info->phys_base);
|
||||
|
257
makedumpfile-fix-KASLR-for-sadump.patch
Normal file
257
makedumpfile-fix-KASLR-for-sadump.patch
Normal file
@ -0,0 +1,257 @@
|
||||
From: Takao Indoh <indou.takao@jp.fujitsu.com>
|
||||
Date: Thu, 26 Oct 2017 20:32:54 +0900
|
||||
Subject: Fix a KASLR problem of sadump
|
||||
References: FATE#323473, bsc#1070291
|
||||
Upstream: merged
|
||||
Git-commit: e1ac694b94ebfa7204c5b1fac1a87d204b48f5b4
|
||||
|
||||
This patch fix a problem that makedumpfile cannot handle a dumpfile
|
||||
which is captured by sadump in KASLR enabled kernel.
|
||||
|
||||
When KASLR feature is enabled, a kernel is placed on the memory randomly
|
||||
and therefore makedumpfile cannot handle a dumpfile captured by sadump
|
||||
because addresses of kernel symbols in System.map or vmlinux are
|
||||
different from actual addresses.
|
||||
|
||||
To solve this problem, we need to calculate kaslr offset(the difference
|
||||
between original symbol address and actual address) and phys_base, and
|
||||
adjust symbol table of makedumpfile. In the case of dumpfile of kdump,
|
||||
these information is included in the header, but dumpfile of sadump does
|
||||
not have such a information.
|
||||
|
||||
This patch calculate kaslr offset and phys_base to solve this problem.
|
||||
Please see the comment in the calc_kaslr_offset() for the detail idea.
|
||||
The basic idea is getting register (IDTR and CR3) from dump header, and
|
||||
calculate kaslr_offset/phys_base using them.
|
||||
|
||||
Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
|
||||
Acked-by: Petr Tesarik <ptesarik@suse.com>
|
||||
|
||||
---
|
||||
makedumpfile.c | 10 +++
|
||||
makedumpfile.h | 5 +
|
||||
sadump_info.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
3 files changed, 155 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/makedumpfile.c
|
||||
+++ b/makedumpfile.c
|
||||
@@ -1554,6 +1554,9 @@ get_symbol_info(void)
|
||||
SYMBOL_INIT(demote_segment_4k, "demote_segment_4k");
|
||||
SYMBOL_INIT(cur_cpu_spec, "cur_cpu_spec");
|
||||
|
||||
+ SYMBOL_INIT(divide_error, "divide_error");
|
||||
+ SYMBOL_INIT(idt_table, "idt_table");
|
||||
+
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -2251,6 +2254,13 @@ write_vmcoreinfo_data(void)
|
||||
WRITE_NUMBER_UNSIGNED("kimage_voffset", kimage_voffset);
|
||||
#endif
|
||||
|
||||
+ if (info->phys_base)
|
||||
+ fprintf(info->file_vmcoreinfo, "%s%lu\n", STR_NUMBER("phys_base"),
|
||||
+ info->phys_base);
|
||||
+ if (info->kaslr_offset)
|
||||
+ fprintf(info->file_vmcoreinfo, "%s%lx\n", STR_KERNELOFFSET,
|
||||
+ info->kaslr_offset);
|
||||
+
|
||||
/*
|
||||
* write the source file of 1st kernel
|
||||
*/
|
||||
--- a/makedumpfile.h
|
||||
+++ b/makedumpfile.h
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "sadump_mod.h"
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
+#include <inttypes.h>
|
||||
|
||||
#define VMEMMAPSTART 0xffffea0000000000UL
|
||||
#define BITS_PER_WORD 64
|
||||
@@ -1593,6 +1594,8 @@ struct symbol_table {
|
||||
unsigned long long cpu_online_mask;
|
||||
unsigned long long __cpu_online_mask;
|
||||
unsigned long long kexec_crash_image;
|
||||
+ unsigned long long divide_error;
|
||||
+ unsigned long long idt_table;
|
||||
|
||||
/*
|
||||
* symbols on ppc64 arch
|
||||
@@ -1953,7 +1956,7 @@ int iomem_for_each_line(char *match, int
|
||||
unsigned long base,
|
||||
unsigned long length),
|
||||
void *data);
|
||||
-
|
||||
+int get_symbol_info(void);
|
||||
|
||||
/*
|
||||
* for Xen extraction
|
||||
--- a/sadump_info.c
|
||||
+++ b/sadump_info.c
|
||||
@@ -1035,6 +1035,138 @@ sadump_get_max_mapnr(void)
|
||||
|
||||
#ifdef __x86_64__
|
||||
|
||||
+/*
|
||||
+ * Get address of vector0 interrupt handler (Devide Error) form Interrupt
|
||||
+ * Descriptor Table.
|
||||
+ */
|
||||
+static unsigned long
|
||||
+get_vec0_addr(ulong idtr)
|
||||
+{
|
||||
+ struct gate_struct64 {
|
||||
+ uint16_t offset_low;
|
||||
+ uint16_t segment;
|
||||
+ uint32_t ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
|
||||
+ uint16_t offset_middle;
|
||||
+ uint32_t offset_high;
|
||||
+ uint32_t zero1;
|
||||
+ } __attribute__((packed)) gate;
|
||||
+
|
||||
+ readmem(PADDR, idtr, &gate, sizeof(gate));
|
||||
+
|
||||
+ return ((ulong)gate.offset_high << 32)
|
||||
+ + ((ulong)gate.offset_middle << 16)
|
||||
+ + gate.offset_low;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Calculate kaslr_offset and phys_base
|
||||
+ *
|
||||
+ * kaslr_offset:
|
||||
+ * The difference between original address in vmlinux and actual address
|
||||
+ * placed randomly by kaslr feature. To be more accurate,
|
||||
+ * kaslr_offset = actual address - original address
|
||||
+ *
|
||||
+ * phys_base:
|
||||
+ * Physical address where the kerenel is placed. In other words, it's a
|
||||
+ * physical address of __START_KERNEL_map. This is also decided randomly by
|
||||
+ * kaslr.
|
||||
+ *
|
||||
+ * kaslr offset and phys_base are calculated as follows:
|
||||
+ *
|
||||
+ * kaslr_offset:
|
||||
+ * 1) Get IDTR and CR3 value from the dump header.
|
||||
+ * 2) Get a virtual address of IDT from IDTR value
|
||||
+ * --- (A)
|
||||
+ * 3) Translate (A) to physical address using CR3, which points a top of
|
||||
+ * page table.
|
||||
+ * --- (B)
|
||||
+ * 4) Get an address of vector0 (Devide Error) interrupt handler from
|
||||
+ * IDT, which are pointed by (B).
|
||||
+ * --- (C)
|
||||
+ * 5) Get an address of symbol "divide_error" form vmlinux
|
||||
+ * --- (D)
|
||||
+ *
|
||||
+ * Now we have two addresses:
|
||||
+ * (C)-> Actual address of "divide_error"
|
||||
+ * (D)-> Original address of "divide_error" in the vmlinux
|
||||
+ *
|
||||
+ * kaslr_offset can be calculated by the difference between these two
|
||||
+ * value.
|
||||
+ *
|
||||
+ * phys_base;
|
||||
+ * 1) Get IDT virtual address from vmlinux
|
||||
+ * --- (E)
|
||||
+ *
|
||||
+ * So phys_base can be calculated using relationship of directly mapped
|
||||
+ * address.
|
||||
+ *
|
||||
+ * phys_base =
|
||||
+ * Physical address(B) -
|
||||
+ * (Virtual address(E) + kaslr_offset - __START_KERNEL_map)
|
||||
+ *
|
||||
+ * Note that the address (A) cannot be used instead of (E) because (A) is
|
||||
+ * not direct map address, it's a fixed map address.
|
||||
+ */
|
||||
+int
|
||||
+calc_kaslr_offset(void)
|
||||
+{
|
||||
+ struct sadump_header *sh = si->sh_memory;
|
||||
+ uint64_t idtr = 0, cr3 = 0, idtr_paddr;
|
||||
+ struct sadump_smram_cpu_state smram, zero;
|
||||
+ int apicid;
|
||||
+ unsigned long divide_error_vmcore, divide_error_vmlinux;
|
||||
+ unsigned long kaslr_offset, phys_base;
|
||||
+
|
||||
+ memset(&zero, 0, sizeof(zero));
|
||||
+ for (apicid = 0; apicid < sh->nr_cpus; ++apicid) {
|
||||
+ if (!get_smram_cpu_state(apicid, &smram)) {
|
||||
+ ERRMSG("get_smram_cpu_state error\n");
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ if (memcmp(&smram, &zero, sizeof(smram)) != 0)
|
||||
+ break;
|
||||
+ }
|
||||
+ if (apicid >= sh->nr_cpus) {
|
||||
+ ERRMSG("Can't get smram state\n");
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+
|
||||
+ idtr = ((uint64_t)smram.IdtUpper)<<32 | (uint64_t)smram.IdtLower;
|
||||
+ cr3 = smram.Cr3;
|
||||
+
|
||||
+ /* Convert virtual address of IDT table to physical address */
|
||||
+ if ((idtr_paddr = vtop4_x86_64_pagetable(idtr, cr3)) == NOT_PADDR)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ /* Now we can calculate kaslr_offset and phys_base */
|
||||
+ divide_error_vmlinux = SYMBOL(divide_error);
|
||||
+ divide_error_vmcore = get_vec0_addr(idtr_paddr);
|
||||
+ kaslr_offset = divide_error_vmcore - divide_error_vmlinux;
|
||||
+ phys_base = idtr_paddr -
|
||||
+ (SYMBOL(idt_table) + kaslr_offset - __START_KERNEL_map);
|
||||
+
|
||||
+ info->kaslr_offset = kaslr_offset;
|
||||
+ info->phys_base = phys_base;
|
||||
+
|
||||
+ DEBUG_MSG("sadump: idtr=%" PRIx64 "\n", idtr);
|
||||
+ DEBUG_MSG("sadump: cr3=%" PRIx64 "\n", cr3);
|
||||
+ DEBUG_MSG("sadump: idtr(phys)=%" PRIx64 "\n", idtr_paddr);
|
||||
+ DEBUG_MSG("sadump: devide_error(vmlinux)=%lx\n",
|
||||
+ divide_error_vmlinux);
|
||||
+ DEBUG_MSG("sadump: devide_error(vmcore)=%lx\n",
|
||||
+ divide_error_vmcore);
|
||||
+
|
||||
+ /* Reload symbol */
|
||||
+ if (!get_symbol_info())
|
||||
+ return FALSE;
|
||||
+
|
||||
+ DEBUG_MSG("sadump: kaslr_offset=%lx\n", info->kaslr_offset);
|
||||
+ DEBUG_MSG("sadump: phys_base=%lx\n", info->phys_base);
|
||||
+
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
int
|
||||
sadump_virt_phys_base(void)
|
||||
{
|
||||
@@ -1065,6 +1197,9 @@ sadump_virt_phys_base(void)
|
||||
}
|
||||
|
||||
failed:
|
||||
+ if (calc_kaslr_offset())
|
||||
+ return TRUE;
|
||||
+
|
||||
info->phys_base = 0;
|
||||
|
||||
DEBUG_MSG("sadump: failed to calculate phys_base; default to 0\n");
|
||||
@@ -1518,10 +1653,14 @@ cpu_to_apicid(int cpu, int *apicid)
|
||||
if (!readmem(VADDR, SYMBOL(x86_bios_cpu_apicid_early_ptr),
|
||||
&early_ptr, sizeof(early_ptr)))
|
||||
return FALSE;
|
||||
-
|
||||
+ /*
|
||||
+ * Note: SYMBOL(name) value is adjusted by info->kaslr_offset,
|
||||
+ * but per_cpu symbol does not need to be adjusted becasue it
|
||||
+ * is not affected by kaslr.
|
||||
+ */
|
||||
apicid_addr = early_ptr
|
||||
? SYMBOL(x86_bios_cpu_apicid_early_map)+cpu*sizeof(uint16_t)
|
||||
- : per_cpu_ptr(SYMBOL(x86_bios_cpu_apicid), cpu);
|
||||
+ : per_cpu_ptr(SYMBOL(x86_bios_cpu_apicid) - info->kaslr_offset, cpu);
|
||||
|
||||
if (!readmem(VADDR, apicid_addr, &apicid_u16, sizeof(uint16_t)))
|
||||
return FALSE;
|
@ -1,7 +1,10 @@
|
||||
From: Jeff Mahoney <jeffm@suse.com>
|
||||
Subject: handle renamed init_level4_pgt -> init_top_pgt
|
||||
Patch-mainline: Submitted to kexec-ml, 6 Nov 2017
|
||||
References: bsc#1066770
|
||||
Upstream: merged
|
||||
Git-commit: 97e156b493c46fabfc4b136ab834a6495166ac66
|
||||
|
||||
* Required for kernel 4.13
|
||||
|
||||
Linux 4.13 renamed init_level4_pgt to init_top_pgt in preparation for
|
||||
introducing 5-level page tables. This patch follows the rename if
|
||||
|
@ -1,6 +1,6 @@
|
||||
From: Petr Tesarik <ptesarik@suse.com>
|
||||
Subject: Allow to override the tinfo library used for eppic
|
||||
Patch-mainline: never; only needed for compatibility with older ncurses
|
||||
Upstream: never; only needed for compatibility with older ncurses
|
||||
|
||||
Allow to override the "-ltinfo" linker option with a make variable.
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
From 13f48cbab7207d8247834453b55d45b2a95f65cb Mon Sep 17 00:00:00 2001
|
||||
From: Hari Bathini <hbathini@linux.vnet.ibm.com>
|
||||
Date: Sat, 11 Nov 2017 02:13:54 +0900
|
||||
Subject: [PATCH] [PATCH] ppc64: update hash page table geometry
|
||||
|
||||
Patch-mainline: yes
|
||||
Subject: ppc64: update hash page table geometry
|
||||
References: bsc#1067703
|
||||
Upsream: merged
|
||||
Git-commit: 13f48cbab7207d8247834453b55d45b2a95f65cb
|
||||
|
||||
* Required for kernel 4.12
|
||||
|
||||
Starting with kernel 4.12, BOOK3S hash page table geometry is updated
|
||||
|
110
makedumpfile-vtop4_x86_64_pagetable.patch
Normal file
110
makedumpfile-vtop4_x86_64_pagetable.patch
Normal file
@ -0,0 +1,110 @@
|
||||
From: Takao Indoh <indou.takao@jp.fujitsu.com>
|
||||
Date: Thu, 26 Oct 2017 20:32:54 +0900
|
||||
Subject: Introduce vtop4_x86_64_pagetable
|
||||
References: FATE#323473, bsc#1070291
|
||||
Upstream: merged
|
||||
Git-commit: 8c89727155f4994b4e75a659e28e5eff16ff6cbc
|
||||
|
||||
This patch introduces new function vtop4_x86_64_pagetable
|
||||
to translate virtual address to physical address. Unlike vtop4_x86_64,
|
||||
vtop4_x86_64_pagetable need a pointer of top of pagetable like CR3.
|
||||
|
||||
Current vtop4_x86_64 implementation uses symbol value of
|
||||
init_level4_pgt, therefore vtop4_x86_64 does not work for sadump
|
||||
dumpfile of kaslr enabled kernel because it does not have vmcoreinfo to
|
||||
correct address of init_level4_pgt. vtop4_x86_64_pagetable requires
|
||||
pagetable address instead of init_level4_pgt and sadump dumpfile can
|
||||
pass CR3 value which is included in dump header.
|
||||
|
||||
Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
|
||||
Signed-off-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
|
||||
Acked-by: Petr Tesarik <ptesarik@suse.com>
|
||||
|
||||
---
|
||||
arch/x86_64.c | 50 +++++++++++++++++++++++++++++++++-----------------
|
||||
makedumpfile.h | 1 +
|
||||
2 files changed, 34 insertions(+), 17 deletions(-)
|
||||
|
||||
--- a/arch/x86_64.c
|
||||
+++ b/arch/x86_64.c
|
||||
@@ -255,30 +255,15 @@ get_versiondep_info_x86_64(void)
|
||||
* Translate a virtual address to a physical address by using 4 levels paging.
|
||||
*/
|
||||
unsigned long long
|
||||
-vtop4_x86_64(unsigned long vaddr)
|
||||
+__vtop4_x86_64(unsigned long vaddr, unsigned long pagetable)
|
||||
{
|
||||
unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
|
||||
unsigned long pte_paddr, pte;
|
||||
- unsigned long init_level4_pgt;
|
||||
-
|
||||
- if (SYMBOL(init_level4_pgt) != NOT_FOUND_SYMBOL)
|
||||
- init_level4_pgt = SYMBOL(init_level4_pgt);
|
||||
- else if (SYMBOL(init_top_pgt) != NOT_FOUND_SYMBOL)
|
||||
- init_level4_pgt = SYMBOL(init_top_pgt);
|
||||
- else {
|
||||
- ERRMSG("Can't get the symbol of init_level4_pgt.\n");
|
||||
- return NOT_PADDR;
|
||||
- }
|
||||
-
|
||||
- if (SYMBOL(level4_kernel_pgt) != NOT_FOUND_SYMBOL) {
|
||||
- ERRMSG("Kernel is built with 5-level page tables\n");
|
||||
- return NOT_PADDR;
|
||||
- }
|
||||
|
||||
/*
|
||||
* Get PGD.
|
||||
*/
|
||||
- page_dir = init_level4_pgt - __START_KERNEL_map + info->phys_base;
|
||||
+ page_dir = pagetable;
|
||||
if (is_xen_memory()) {
|
||||
page_dir = ptom_xen(page_dir);
|
||||
if (page_dir == NOT_PADDR)
|
||||
@@ -356,6 +341,37 @@ vtop4_x86_64(unsigned long vaddr)
|
||||
return (pte & ENTRY_MASK) + PAGEOFFSET(vaddr);
|
||||
}
|
||||
|
||||
+unsigned long long
|
||||
+vtop4_x86_64(unsigned long vaddr)
|
||||
+{
|
||||
+ unsigned long pagetable;
|
||||
+ unsigned long init_level4_pgt;
|
||||
+
|
||||
+ if (SYMBOL(init_level4_pgt) != NOT_FOUND_SYMBOL)
|
||||
+ init_level4_pgt = SYMBOL(init_level4_pgt);
|
||||
+ else if (SYMBOL(init_top_pgt) != NOT_FOUND_SYMBOL)
|
||||
+ init_level4_pgt = SYMBOL(init_top_pgt);
|
||||
+ else {
|
||||
+ ERRMSG("Can't get the symbol of init_level4_pgt.\n");
|
||||
+ return NOT_PADDR;
|
||||
+ }
|
||||
+
|
||||
+ if (SYMBOL(level4_kernel_pgt) != NOT_FOUND_SYMBOL) {
|
||||
+ ERRMSG("Kernel is built with 5-level page tables\n");
|
||||
+ return NOT_PADDR;
|
||||
+ }
|
||||
+
|
||||
+ pagetable = init_level4_pgt - __START_KERNEL_map + info->phys_base;
|
||||
+
|
||||
+ return __vtop4_x86_64(vaddr, pagetable);
|
||||
+}
|
||||
+
|
||||
+unsigned long long
|
||||
+vtop4_x86_64_pagetable(unsigned long vaddr, unsigned long pagetable)
|
||||
+{
|
||||
+ return __vtop4_x86_64(vaddr, pagetable);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* for Xen extraction
|
||||
*/
|
||||
--- a/makedumpfile.h
|
||||
+++ b/makedumpfile.h
|
||||
@@ -977,6 +977,7 @@ int get_phys_base_x86_64(void);
|
||||
int get_machdep_info_x86_64(void);
|
||||
int get_versiondep_info_x86_64(void);
|
||||
unsigned long long vtop4_x86_64(unsigned long vaddr);
|
||||
+unsigned long long vtop4_x86_64_pagetable(unsigned long vaddr, unsigned long pagetable);
|
||||
#define find_vmemmap() find_vmemmap_x86_64()
|
||||
#define get_phys_base() get_phys_base_x86_64()
|
||||
#define get_machdep_info() get_machdep_info_x86_64()
|
@ -1,3 +1,16 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Jan 9 09:56:06 UTC 2018 - ptesarik@suse.com
|
||||
|
||||
- makedumpfile-__cpu_online_mask-symbol.patch: Support symbol
|
||||
__cpu_online_mask (FATE#323473, bsc#1070291).
|
||||
- makedumpfile-vtop4_x86_64_pagetable.patch: Introduce
|
||||
vtop4_x86_64_pagetable (FATE#323473, bsc#1070291).
|
||||
- makedumpfile-fix-KASLR-for-sadump.patch: Fix a KASLR problem of
|
||||
sadump (FATE#323473, bsc#1070291).
|
||||
- makedumpfile-fix-KASLR-for-sadump-while-kdump.patch: sadump: Fix
|
||||
a KASLR problem of sadump while kdump is working (FATE#323473,
|
||||
bsc#1070291).
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Nov 15 18:05:58 UTC 2017 - msuchanek@suse.com
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# spec file for package makedumpfile
|
||||
#
|
||||
# Copyright (c) 2017 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
||||
# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
@ -43,6 +43,10 @@ Patch2: %{name}-override-libtinfo.patch
|
||||
Patch3: %{name}-handle-renamed-init_level4_pgt-init_top_pgt.patch
|
||||
Patch4: %{name}-ppc64-update-hash-page-table-geometry.patch
|
||||
Patch5: %{name}-book3s-ppc64-Lower-the-max-real-address-to-53-bits.patch
|
||||
Patch6: %{name}-__cpu_online_mask-symbol.patch
|
||||
Patch7: %{name}-vtop4_x86_64_pagetable.patch
|
||||
Patch8: %{name}-fix-KASLR-for-sadump.patch
|
||||
Patch9: %{name}-fix-KASLR-for-sadump-while-kdump.patch
|
||||
BuildRequires: libdw-devel
|
||||
BuildRequires: libebl-devel
|
||||
BuildRequires: libelf-devel
|
||||
@ -76,6 +80,10 @@ via gdb or crash utility.
|
||||
%patch3 -p1
|
||||
%patch4 -p1
|
||||
%patch5 -p1
|
||||
%patch6 -p1
|
||||
%patch7 -p1
|
||||
%patch8 -p1
|
||||
%patch9 -p1
|
||||
|
||||
%build
|
||||
%if %{have_snappy}
|
||||
|
Loading…
Reference in New Issue
Block a user