commit 1e488cfefa1d9ca4ca626bc2a308b39f7404f5db
Author: Dave Anderson <anderson@redhat.com>
Date: Tue Jan 23 16:35:41 2018 -0500
Fix for the "bt" command and the "ps -s" option for zombie tasks
whose kernel stacks have been freed/detached. Without the patch,
the "bt" command indicates "bt: invalid kernel virtual address: 0
type: stack contents" and "bt: read of stack at 0 failed"; it will
be changed to display "(no stack)". The "ps -s" option would fail
prematurely upon reaching such a task, indicating "ps: invalid kernel
virtual address: 0 type: stack contents" and "ps: read of stack at 0
failed".
(anderson@redhat.com)
diff --git a/kernel.c b/kernel.c
index 4638495..1bf6251 100644
--- a/kernel.c
+++ b/kernel.c
@@ -1,8 +1,8 @@
/* kernel.c - core analysis suite
*
* Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
- * Copyright (C) 2002-2017 David Anderson
- * Copyright (C) 2002-2017 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2002-2018 David Anderson
+ * Copyright (C) 2002-2018 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -2890,6 +2890,11 @@ back_trace(struct bt_info *bt)
return;
}
+ if (bt->stackbase == 0) {
+ fprintf(fp, "(no stack)\n");
+ return;
+ }
+
fill_stackbuf(bt);
if (CRASHDEBUG(4)) {
diff --git a/task.c b/task.c
index b303ef7..db05ab4 100644
--- a/task.c
+++ b/task.c
@@ -1,8 +1,8 @@
/* task.c - core analysis suite
*
* Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
- * Copyright (C) 2002-2017 David Anderson
- * Copyright (C) 2002-2017 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2002-2018 David Anderson
+ * Copyright (C) 2002-2018 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -4182,12 +4182,14 @@ task_pointer_string(struct task_context *tc, ulong do_kstackp, char *buf)
KVADDR, &bt->stkptr, sizeof(void *),
"thread_struct ksp", FAULT_ON_ERROR);
} else {
- bt->task = tc->task;
- bt->tc = tc;
- bt->stackbase = GET_STACKBASE(tc->task);
- bt->stacktop = GET_STACKTOP(tc->task);
- bt->flags |= BT_KSTACKP;
- back_trace(bt);
+ if ((bt->stackbase = GET_STACKBASE(tc->task))) {
+ bt->stacktop = GET_STACKTOP(tc->task);
+ bt->task = tc->task;
+ bt->tc = tc;
+ bt->flags |= BT_KSTACKP;
+ back_trace(bt);
+ } else
+ bt->stkptr = 0;
}
if (bt->stkptr)
commit 693e0fa8ea8b2791329a4197fafd8700afa14c3b
Author: Dave Anderson <anderson@redhat.com>
Date: Thu Jan 25 14:52:54 2018 -0500
Fix for running on live systems on 4.15-rc2 and later kernels that
are configured with CONFIG_RANDOMIZE_BASE and contain kernel commit
668533dc0764b30c9dd2baf3ca800156f688326b, titled "kallsyms: take
advantage of the new '%px' format". Without the patch, a live crash
session does not show the "WARNING: kernel relocated ..." message
expected with KASLR, and then displays the message "crash: cannot set
context for pid: <pid>" prior to generating a SIGSEGV.
(anderson@redhat.com)
diff --git a/symbols.c b/symbols.c
index 2372887..9a3763c 100644
--- a/symbols.c
+++ b/symbols.c
@@ -1,8 +1,8 @@
/* symbols.c - core analysis suite
*
* Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
- * Copyright (C) 2002-2017 David Anderson
- * Copyright (C) 2002-2017 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2002-2018 David Anderson
+ * Copyright (C) 2002-2018 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1004,10 +1004,9 @@ symbol_value_from_proc_kallsyms(char *symname)
found = FALSE;
while (!found && fgets(buf, BUFSIZE, kp) &&
- (parse_line(buf, kallsyms) == 3) &&
- hexadecimal(kallsyms[0], 0)) {
-
- if (STREQ(kallsyms[2], symname)) {
+ (parse_line(buf, kallsyms) == 3)) {
+ if (hexadecimal(kallsyms[0], 0) &&
+ STREQ(kallsyms[2], symname)) {
kallsym = htol(kallsyms[0], RETURN_ON_ERROR, NULL);
found = TRUE;
break;
commit 1af7813e0552ac93b39a44abffffc04600d3ed4c
Author: Dave Anderson <anderson@redhat.com>
Date: Thu Jan 25 15:17:26 2018 -0500
Fix for 4.15-rc5 and later x86_64 kernels that contain kernel commit
c482feefe1aeb150156248ba0fd3e029bc886605, titled "x86/entry/64: Make
cpu_entry_area.tss read-only". Without the patch, the addresses and
sizes of the x86_64 exception stacks cannot be determined; therefore
if a backtrace starts on one of the exception stacks, then the "bt"
command will fail.
(anderson@redhat.com)
diff --git a/x86_64.c b/x86_64.c
index e924ca9..467b5d7 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -1245,8 +1245,10 @@ x86_64_ist_init(void)
struct syment *boot_sp, *tss_sp, *ist_sp;
ms = machdep->machspec;
- if (!(tss_sp = per_cpu_symbol_search("per_cpu__init_tss")))
- tss_sp = per_cpu_symbol_search("per_cpu__cpu_tss");
+ if (!(tss_sp = per_cpu_symbol_search("per_cpu__init_tss"))) {
+ if (!(tss_sp = per_cpu_symbol_search("per_cpu__cpu_tss")))
+ tss_sp = per_cpu_symbol_search("per_cpu__cpu_tss_rw");
+ }
ist_sp = per_cpu_symbol_search("per_cpu__orig_ist");
x86_64_exception_stacks_init();
commit 1160ba19884fed4420c334394cde7a40b113e09c
Author: Dave Anderson <anderson@redhat.com>
Date: Fri Jan 26 11:06:48 2018 -0500
Additional fix for support of KASLR enabled kernels captured by the
SADUMP dumpfile facility, where this patch fixes a problem when Page
Table Isolation(PTI) is enabled. When PTI is enabled, bit 12 of CR3
register is used to split user space and kernel space. Also bit 11:0
is used for Process Context IDentifiers(PCID). To open an SADUMP
dumpfile, the value of CR3 is used to calculate KASLR offset and
phys_base; this patch masks the CR3 register value correctly for
a PTI enabled kernel.
(indou.takao@jp.fujitsu.com)
diff --git a/defs.h b/defs.h
index 4d2fb2f..92341d2 100644
--- a/defs.h
+++ b/defs.h
@@ -2605,6 +2605,8 @@ struct symbol_table_data {
ulong divide_error_vmlinux;
ulong idt_table_vmlinux;
ulong saved_command_line_vmlinux;
+ ulong pti_init_vmlinux;
+ ulong kaiser_init_vmlinux;
};
/* flags for st */
diff --git a/sadump.c b/sadump.c
index 6b912d4..25cefe9 100644
--- a/sadump.c
+++ b/sadump.c
@@ -1749,7 +1749,7 @@ static ulong memparse(char *ptr, char **retptr)
* of elfcorehdr.
*/
static ulong
-get_elfcorehdr(ulong cr3, ulong kaslr_offset)
+get_elfcorehdr(ulong kaslr_offset)
{
char cmdline[BUFSIZE], *ptr;
ulong cmdline_vaddr;
@@ -1906,7 +1906,7 @@ get_vmcoreinfo(ulong elfcorehdr, ulong *addr, int *len)
* using "elfcorehdr=" and retrieve kaslr_offset/phys_base from vmcoreinfo.
*/
static int
-get_kaslr_offset_from_vmcoreinfo(ulong cr3, ulong orig_kaslr_offset,
+get_kaslr_offset_from_vmcoreinfo(ulong orig_kaslr_offset,
ulong *kaslr_offset, ulong *phys_base)
{
ulong elfcorehdr_addr = 0;
@@ -1916,7 +1916,7 @@ get_kaslr_offset_from_vmcoreinfo(ulong cr3, ulong orig_kaslr_offset,
int ret = FALSE;
/* Find "elfcorehdr=" in the kernel boot parameter */
- elfcorehdr_addr = get_elfcorehdr(cr3, orig_kaslr_offset);
+ elfcorehdr_addr = get_elfcorehdr(orig_kaslr_offset);
if (!elfcorehdr_addr)
return FALSE;
@@ -1973,8 +1973,8 @@ quit:
* 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.
+ * 3) Translate (A) to physical address using CR3, the upper 52 bits
+ * of 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).
@@ -2023,12 +2023,15 @@ quit:
* kernel. Retrieve vmcoreinfo from address of "elfcorehdr=" and
* get kaslr_offset and phys_base from vmcoreinfo.
*/
+#define PTI_USER_PGTABLE_BIT PAGE_SHIFT
+#define PTI_USER_PGTABLE_MASK (1 << PTI_USER_PGTABLE_BIT)
+#define CR3_PCID_MASK 0xFFFull
int
sadump_calc_kaslr_offset(ulong *kaslr_offset)
{
ulong phys_base = 0;
struct sadump_smram_cpu_state scs;
- uint64_t idtr = 0, cr3 = 0, idtr_paddr;
+ uint64_t idtr = 0, pgd = 0, idtr_paddr;
ulong divide_error_vmcore;
ulong kaslr_offset_kdump, phys_base_kdump;
int ret = FALSE;
@@ -2039,7 +2042,10 @@ sadump_calc_kaslr_offset(ulong *kaslr_offset)
memset(&scs, 0, sizeof(scs));
get_sadump_smram_cpu_state_any(&scs);
- cr3 = scs.Cr3;
+ if (st->pti_init_vmlinux || st->kaiser_init_vmlinux)
+ pgd = scs.Cr3 & ~(CR3_PCID_MASK|PTI_USER_PGTABLE_MASK);
+ else
+ pgd = scs.Cr3 & ~CR3_PCID_MASK;
idtr = ((uint64_t)scs.IdtUpper)<<32 | (uint64_t)scs.IdtLower;
/*
@@ -2050,12 +2056,12 @@ sadump_calc_kaslr_offset(ulong *kaslr_offset)
*
* TODO: XEN and 5-level is not supported
*/
- vt->kernel_pgd[0] = cr3;
+ vt->kernel_pgd[0] = pgd;
machdep->machspec->last_pml4_read = vt->kernel_pgd[0];
machdep->machspec->physical_mask_shift = __PHYSICAL_MASK_SHIFT_2_6;
machdep->machspec->pgdir_shift = PGDIR_SHIFT;
- if (!readmem(cr3, PHYSADDR, machdep->machspec->pml4, PAGESIZE(),
- "cr3", RETURN_ON_ERROR))
+ if (!readmem(pgd, PHYSADDR, machdep->machspec->pml4, PAGESIZE(),
+ "pgd", RETURN_ON_ERROR))
goto quit;
/* Convert virtual address of IDT table to physical address */
@@ -2070,7 +2076,7 @@ sadump_calc_kaslr_offset(ulong *kaslr_offset)
if (CRASHDEBUG(1)) {
fprintf(fp, "calc_kaslr_offset: idtr=%lx\n", idtr);
- fprintf(fp, "calc_kaslr_offset: cr3=%lx\n", cr3);
+ fprintf(fp, "calc_kaslr_offset: pgd=%lx\n", pgd);
fprintf(fp, "calc_kaslr_offset: idtr(phys)=%lx\n", idtr_paddr);
fprintf(fp, "calc_kaslr_offset: divide_error(vmlinux): %lx\n",
st->divide_error_vmlinux);
@@ -2084,9 +2090,12 @@ sadump_calc_kaslr_offset(ulong *kaslr_offset)
* from vmcoreinfo
*/
if (get_kaslr_offset_from_vmcoreinfo(
- cr3, *kaslr_offset, &kaslr_offset_kdump, &phys_base_kdump)) {
+ *kaslr_offset, &kaslr_offset_kdump, &phys_base_kdump)) {
*kaslr_offset = kaslr_offset_kdump;
phys_base = phys_base_kdump;
+ } else if (CRASHDEBUG(1)) {
+ fprintf(fp, "sadump: failed to determine which kernel was running at crash,\n");
+ fprintf(fp, "sadump: asssuming the kdump 1st kernel.\n");
}
if (CRASHDEBUG(1)) {
diff --git a/symbols.c b/symbols.c
index 9a3763c..4db9af7 100644
--- a/symbols.c
+++ b/symbols.c
@@ -3071,10 +3071,14 @@ dump_symbol_table(void)
fprintf(fp, "divide_error_vmlinux: %lx\n", st->divide_error_vmlinux);
fprintf(fp, " idt_table_vmlinux: %lx\n", st->idt_table_vmlinux);
fprintf(fp, "saved_command_line_vmlinux: %lx\n", st->saved_command_line_vmlinux);
+ fprintf(fp, " pti_init_vmlinux: %lx\n", st->pti_init_vmlinux);
+ fprintf(fp, " kaiser_init_vmlinux: %lx\n", st->kaiser_init_vmlinux);
} else {
fprintf(fp, "divide_error_vmlinux: (unused)\n");
fprintf(fp, " idt_table_vmlinux: (unused)\n");
fprintf(fp, "saved_command_line_vmlinux: (unused)\n");
+ fprintf(fp, " pti_init_vmlinux: (unused)\n");
+ fprintf(fp, " kaiser_init_vmlinux: (unused)\n");
}
fprintf(fp, " symval_hash[%d]: %lx\n", SYMVAL_HASH,
@@ -12305,6 +12309,11 @@ numeric_forward(const void *P_x, const void *P_y)
st->saved_command_line_vmlinux = valueof(x);
else if (STREQ(y->name, "saved_command_line"))
st->saved_command_line_vmlinux = valueof(y);
+
+ if (STREQ(x->name, "pti_init"))
+ st->pti_init_vmlinux = valueof(x);
+ else if (STREQ(y->name, "kaiser_init"))
+ st->kaiser_init_vmlinux = valueof(y);
}
xs = bfd_get_section(x);