[Crash-utility] [PATCH v4 5/6] vmware_vmss: infer kaslr offset for VMSS dumps

Sergio Lopez slp at redhat.com
Tue Mar 27 10:09:51 UTC 2018


VMware does not provide support for saving and including the vmcoreinfo
data into a VM dump. This patch adds support for calculating phys_base
and kaslr_offset for KASLR-enabled kernels, using the technique
developed by Takao Indoh.
---
 defs.h         |  3 +++
 kaslr_helper.c |  3 +++
 symbols.c      | 10 ++++++----
 vmware_vmss.c  | 28 ++++++++++++++++++++++++++++
 vmware_vmss.h  |  1 +
 x86_64.c       | 20 ++++++++++++++++++--
 6 files changed, 59 insertions(+), 6 deletions(-)

diff --git a/defs.h b/defs.h
index ba2e5e1..3a3b6f6 100644
--- a/defs.h
+++ b/defs.h
@@ -6429,6 +6429,9 @@ void get_vmware_vmss_regs(struct bt_info *, ulong *, ulong *);
 int vmware_vmss_memory_dump(FILE *);
 void dump_registers_for_vmss_dump(void);
 int vmware_vmss_valid_regs(struct bt_info *);
+int vmware_vmss_get_cr3_idtr(ulong *, ulong *);
+int vmware_vmss_phys_base(ulong *phys_base);
+int vmware_vmss_set_phys_base(ulong);
 
 /*
  * kaslr_helper.c
diff --git a/kaslr_helper.c b/kaslr_helper.c
index 168cfb9..8a1fede 100644
--- a/kaslr_helper.c
+++ b/kaslr_helper.c
@@ -409,6 +409,9 @@ calc_kaslr_offset(ulong *kaslr_offset, ulong *phys_base)
 	} else if (QEMU_MEM_DUMP_NO_VMCOREINFO()) {
 		if (!qemu_get_cr3_idtr(&cr3, &idtr))
 			return FALSE;
+	} else if (VMSS_DUMPFILE()) {
+		if (!vmware_vmss_get_cr3_idtr(&cr3, &idtr))
+			return FALSE;
 	} else
 		return FALSE;
 
diff --git a/symbols.c b/symbols.c
index ddbce7d..638800a 100644
--- a/symbols.c
+++ b/symbols.c
@@ -631,7 +631,7 @@ kaslr_init(void)
 		}
 	}
 
-	if (SADUMP_DUMPFILE())
+	if (SADUMP_DUMPFILE() || VMSS_DUMPFILE())
 		kt->flags2 |= KASLR_CHECK;
 }
 
@@ -646,7 +646,7 @@ derive_kaslr_offset(bfd *abfd, int dynamic, bfd_byte *start, bfd_byte *end,
 	unsigned long relocate;
 	ulong _stext_relocated;
 
-	if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO()) {
+	if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO() || VMSS_DUMPFILE()) {
 		ulong kaslr_offset = 0;
 		ulong phys_base = 0;
 
@@ -664,6 +664,8 @@ derive_kaslr_offset(bfd *abfd, int dynamic, bfd_byte *start, bfd_byte *end,
 				kdump_set_phys_base(phys_base);
 			else if (DISKDUMP_DUMPFILE())
 				diskdump_set_phys_base(phys_base);
+			else if (VMSS_DUMPFILE())
+				vmware_vmss_set_phys_base(phys_base);
 		}
 
 		return;
@@ -3083,7 +3085,7 @@ dump_symbol_table(void)
 	else
 		fprintf(fp, "\n");
 
-	if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO()) {
+	if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO() || VMSS_DUMPFILE()) {
 		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);
@@ -12310,7 +12312,7 @@ numeric_forward(const void *P_x, const void *P_y)
 		}
 	}
 
-	if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO()) {
+	if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO() || VMSS_DUMPFILE()) {
 		/* Need for kaslr_offset and phys_base */
 		if (STREQ(x->name, "divide_error"))
 			st->divide_error_vmlinux = valueof(x);
diff --git a/vmware_vmss.c b/vmware_vmss.c
index ad577b2..74c7483 100644
--- a/vmware_vmss.c
+++ b/vmware_vmss.c
@@ -863,3 +863,31 @@ vmware_vmss_valid_regs(struct bt_info *bt)
 
 	return FALSE;
 }
+
+int
+vmware_vmss_get_cr3_idtr(ulong *cr3, ulong *idtr)
+{
+	if (vmss.num_vcpus == 0 || vmss.vcpu_regs[0] != REGS_PRESENT_ALL)
+		return FALSE;
+
+	*cr3 = vmss.regs64[0]->cr[3];
+	*idtr = vmss.regs64[0]->idtr;
+
+	return TRUE;
+}
+
+int
+vmware_vmss_phys_base(ulong *phys_base)
+{
+	*phys_base = vmss.phys_base;
+
+	return TRUE;
+}
+
+int
+vmware_vmss_set_phys_base(ulong phys_base)
+{
+	vmss.phys_base = phys_base;
+
+	return TRUE;
+}
diff --git a/vmware_vmss.h b/vmware_vmss.h
index f6966a5..a5828a0 100644
--- a/vmware_vmss.h
+++ b/vmware_vmss.h
@@ -157,6 +157,7 @@ struct vmssdata {
         memregion	regions[MAX_REGIONS];
 	uint64_t	memoffset;
 	uint64_t	memsize;
+	ulong		phys_base;
 	int		separate_vmem;
 	uint32_t	*vcpu_regs;
 	uint64_t	num_vcpus;
diff --git a/x86_64.c b/x86_64.c
index e46e70f..2934f80 100644
--- a/x86_64.c
+++ b/x86_64.c
@@ -202,7 +202,8 @@ x86_64_init(int when)
 			machdep->machspec->kernel_image_size = dtol(string, QUIET, NULL);
 			free(string);
 		}
-		if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO())
+		if (SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO() ||
+		    VMSS_DUMPFILE())
 			/* Need for calculation of kaslr_offset and phys_base */
 			machdep->kvtop = x86_64_kvtop;
 		break;
@@ -2220,7 +2221,7 @@ x86_64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbo
 	ulong pte;
 	physaddr_t physpage;
 
-	if ((SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO())
+	if ((SADUMP_DUMPFILE() || QEMU_MEM_DUMP_NO_VMCOREINFO() || VMSS_DUMPFILE())
 	    && !(machdep->flags & KSYMS_START)) {
 		/*
 		 * In the case of sadump, to calculate kaslr_offset and
@@ -6654,6 +6655,21 @@ x86_64_calc_phys_base(void)
 		return;
 	}
 
+	if (VMSS_DUMPFILE()) {
+		if (vmware_vmss_phys_base(&phys_base)) {
+			machdep->machspec->phys_base = phys_base;
+			if (!x86_64_virt_phys_base())
+				error(WARNING,
+				    "cannot determine physical base address:"
+				    " defaulting to %lx\n\n",
+					machdep->machspec->phys_base);
+			if (CRASHDEBUG(1))
+				fprintf(fp, "compressed kdump: phys_base: %lx\n",
+				    phys_base);
+		}
+		return;
+	}
+
 	if (DISKDUMP_DUMPFILE()) {
 		if (diskdump_phys_base(&phys_base)) {
 			machdep->machspec->phys_base = phys_base;
-- 
2.14.3




More information about the Crash-utility mailing list