Blob Blame History Raw
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);