Blame SOURCES/kexec-tools-2.0.14-makedumpfile-makedumpfile-add-runtime-kaslr-offset-if-it-exists.patch

23ef29
From 302c16ede3723264ca0abb5eef9c9f553ffcfbd7 Mon Sep 17 00:00:00 2001
23ef29
Message-Id: <302c16ede3723264ca0abb5eef9c9f553ffcfbd7.1496033260.git.panand@redhat.com>
23ef29
From: Pratyush Anand <panand@redhat.com>
23ef29
Date: Wed, 26 Apr 2017 14:36:29 +0530
23ef29
Subject: [PATCH 1/3] makedumpfile: add runtime kaslr offset if it exists
23ef29
23ef29
If we have to erase a symbol from vmcore whose address is not present in
23ef29
vmcoreinfo, then we need to pass vmlinux as well to get the symbol
23ef29
address.
23ef29
When kaslr is enabled, virtual address of all the kernel symbols are
23ef29
randomized with an offset. vmlinux  always has a static address, but all
23ef29
the arch specific calculation are based on run time kernel address. So
23ef29
we need to find a way to translate symbol address from vmlinux to kernel
23ef29
run time address.
23ef29
23ef29
without this patch:
23ef29
   # cat > scrub.conf << EOF
23ef29
   [vmlinux]
23ef29
   erase jiffies
23ef29
   erase init_task.utime
23ef29
   for tsk in init_task.tasks.next within task_struct:tasks
23ef29
       erase tsk.utime
23ef29
   endfor
23ef29
   EOF
23ef29
23ef29
    # makedumpfile --split  -d 5 -x vmlinux --config scrub.conf vmcore dumpfile_{1,2,3}
23ef29
23ef29
    readpage_kdump_compressed: pfn(f97ea) is excluded from vmcore.
23ef29
    readmem: type_addr: 1, addr:f97eaff8, size:8
23ef29
    vtop4_x86_64: Can't get pml4 (page_dir:f97eaff8).
23ef29
    readmem: Can't convert a virtual address(ffffffff819f1284) to physical address.
23ef29
    readmem: type_addr: 0, addr:ffffffff819f1284, size:390
23ef29
    check_release: Can't get the address of system_utsname.
23ef29
23ef29
After this patch check_release() is ok, and also we are able to erase
23ef29
symbol from vmcore.
23ef29
23ef29
Signed-off-by: Pratyush Anand <panand@redhat.com>
23ef29
---
23ef29
 arch/x86_64.c  | 36 ++++++++++++++++++++++++++++++++++++
23ef29
 erase_info.c   |  1 +
23ef29
 makedumpfile.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
23ef29
 makedumpfile.h | 16 ++++++++++++++++
23ef29
 4 files changed, 99 insertions(+)
23ef29
23ef29
diff --git a/makedumpfile-1.6.1/arch/x86_64.c b/makedumpfile-1.6.1/arch/x86_64.c
23ef29
index e978a36f8878..fd2e8ac154d6 100644
23ef29
--- a/makedumpfile-1.6.1/arch/x86_64.c
23ef29
+++ b/makedumpfile-1.6.1/arch/x86_64.c
23ef29
@@ -33,6 +33,42 @@ get_xen_p2m_mfn(void)
23ef29
 	return NOT_FOUND_LONG_VALUE;
23ef29
 }
23ef29
 
23ef29
+unsigned long
23ef29
+get_kaslr_offset_x86_64(unsigned long vaddr)
23ef29
+{
23ef29
+	unsigned int i;
23ef29
+	char buf[BUFSIZE_FGETS], *endp;
23ef29
+
23ef29
+	if (!info->kaslr_offset && info->file_vmcoreinfo) {
23ef29
+		if (fseek(info->file_vmcoreinfo, 0, SEEK_SET) < 0) {
23ef29
+			ERRMSG("Can't seek the vmcoreinfo file(%s). %s\n",
23ef29
+					info->name_vmcoreinfo, strerror(errno));
23ef29
+			return FALSE;
23ef29
+		}
23ef29
+
23ef29
+		while (fgets(buf, BUFSIZE_FGETS, info->file_vmcoreinfo)) {
23ef29
+			i = strlen(buf);
23ef29
+			if (!i)
23ef29
+				break;
23ef29
+			if (buf[i - 1] == '\n')
23ef29
+				buf[i - 1] = '\0';
23ef29
+			if (strncmp(buf, STR_KERNELOFFSET,
23ef29
+					strlen(STR_KERNELOFFSET)) == 0)
23ef29
+				info->kaslr_offset =
23ef29
+					strtoul(buf+strlen(STR_KERNELOFFSET),&endp,16);
23ef29
+		}
23ef29
+	}
23ef29
+	if (vaddr >= __START_KERNEL_map &&
23ef29
+			vaddr < __START_KERNEL_map + info->kaslr_offset)
23ef29
+		return info->kaslr_offset;
23ef29
+	else
23ef29
+		/*
23ef29
+		 * TODO: we need to check if it is vmalloc/vmmemmap/module
23ef29
+		 * address, we will have different offset
23ef29
+		 */
23ef29
+		return 0;
23ef29
+}
23ef29
+
23ef29
 static int
23ef29
 get_page_offset_x86_64(void)
23ef29
 {
23ef29
diff --git a/makedumpfile-1.6.1/erase_info.c b/makedumpfile-1.6.1/erase_info.c
23ef29
index f2ba9149e93e..60abfa1a1adf 100644
23ef29
--- a/makedumpfile-1.6.1/erase_info.c
23ef29
+++ b/makedumpfile-1.6.1/erase_info.c
23ef29
@@ -1088,6 +1088,7 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_vaddr,
23ef29
 							ce->line, ce->name);
23ef29
 			return FALSE;
23ef29
 		}
23ef29
+		ce->sym_addr += get_kaslr_offset(ce->sym_addr);
23ef29
 		ce->type_name = get_symbol_type_name(ce->name,
23ef29
 					DWARF_INFO_GET_SYMBOL_TYPE,
23ef29
 					&ce->size, &ce->type_flag);
23ef29
diff --git a/makedumpfile-1.6.1/makedumpfile.c b/makedumpfile-1.6.1/makedumpfile.c
23ef29
index 301772a8820c..9babf1a07154 100644
23ef29
--- a/makedumpfile-1.6.1/makedumpfile.c
23ef29
+++ b/makedumpfile-1.6.1/makedumpfile.c
23ef29
@@ -3782,6 +3782,46 @@ free_for_parallel()
23ef29
 }
23ef29
 
23ef29
 int
23ef29
+find_kaslr_offsets()
23ef29
+{
23ef29
+	off_t offset;
23ef29
+	unsigned long size;
23ef29
+	int ret = FALSE;
23ef29
+
23ef29
+	get_vmcoreinfo(&offset, &size);
23ef29
+
23ef29
+	if (!(info->name_vmcoreinfo = strdup(FILENAME_VMCOREINFO))) {
23ef29
+		MSG("Can't duplicate strings(%s).\n", FILENAME_VMCOREINFO);
23ef29
+		return FALSE;
23ef29
+	}
23ef29
+	if (!copy_vmcoreinfo(offset, size))
23ef29
+		goto out;
23ef29
+
23ef29
+	if (!open_vmcoreinfo("r"))
23ef29
+		goto out;
23ef29
+
23ef29
+	unlink(info->name_vmcoreinfo);
23ef29
+
23ef29
+	/*
23ef29
+	 * This arch specific function should update info->kaslr_offset. If
23ef29
+	 * kaslr is not enabled then offset will be set to 0. arch specific
23ef29
+	 * function might need to read from vmcoreinfo, therefore we have
23ef29
+	 * called this function between open_vmcoreinfo() and
23ef29
+	 * close_vmcoreinfo()
23ef29
+	 */
23ef29
+	get_kaslr_offset(SYMBOL(_stext));
23ef29
+
23ef29
+	close_vmcoreinfo();
23ef29
+
23ef29
+	ret = TRUE;
23ef29
+out:
23ef29
+	free(info->name_vmcoreinfo);
23ef29
+	info->name_vmcoreinfo = NULL;
23ef29
+
23ef29
+	return ret;
23ef29
+}
23ef29
+
23ef29
+int
23ef29
 initial(void)
23ef29
 {
23ef29
 	off_t offset;
23ef29
@@ -3833,6 +3873,9 @@ initial(void)
23ef29
 		set_dwarf_debuginfo("vmlinux", NULL,
23ef29
 					info->name_vmlinux, info->fd_vmlinux);
23ef29
 
23ef29
+		if (has_vmcoreinfo() && !find_kaslr_offsets())
23ef29
+			return FALSE;
23ef29
+
23ef29
 		if (!get_symbol_info())
23ef29
 			return FALSE;
23ef29
 
23ef29
@@ -8635,6 +8678,7 @@ close_vmcoreinfo(void)
23ef29
 	if(fclose(info->file_vmcoreinfo) < 0)
23ef29
 		ERRMSG("Can't close the vmcoreinfo file(%s). %s\n",
23ef29
 		    info->name_vmcoreinfo, strerror(errno));
23ef29
+	info->file_vmcoreinfo = NULL;
23ef29
 }
23ef29
 
23ef29
 void
23ef29
@@ -11026,11 +11070,13 @@ main(int argc, char *argv[])
23ef29
 		    strerror(errno));
23ef29
 		goto out;
23ef29
 	}
23ef29
+	info->file_vmcoreinfo = NULL;
23ef29
 	info->fd_vmlinux = -1;
23ef29
 	info->fd_xen_syms = -1;
23ef29
 	info->fd_memory = -1;
23ef29
 	info->fd_dumpfile = -1;
23ef29
 	info->fd_bitmap = -1;
23ef29
+	info->kaslr_offset = 0;
23ef29
 	initialize_tables();
23ef29
 
23ef29
 	/*
23ef29
diff --git a/makedumpfile-1.6.1/makedumpfile.h b/makedumpfile-1.6.1/makedumpfile.h
23ef29
index e32e567018f6..9f16becadd55 100644
23ef29
--- a/makedumpfile-1.6.1/makedumpfile.h
23ef29
+++ b/makedumpfile-1.6.1/makedumpfile.h
23ef29
@@ -253,10 +253,14 @@ static inline int string_exists(char *s) { return (s ? TRUE : FALSE); }
23ef29
 #define SYMBOL_INIT(symbol, str_symbol) \
23ef29
 do { \
23ef29
 	SYMBOL(symbol) = get_symbol_addr(str_symbol); \
23ef29
+	if (SYMBOL(symbol) != NOT_FOUND_SYMBOL) \
23ef29
+		SYMBOL(symbol) += info->kaslr_offset; \
23ef29
 } while (0)
23ef29
 #define SYMBOL_INIT_NEXT(symbol, str_symbol) \
23ef29
 do { \
23ef29
 	SYMBOL(symbol) = get_next_symbol_addr(str_symbol); \
23ef29
+	if (SYMBOL(symbol) != NOT_FOUND_SYMBOL) \
23ef29
+		SYMBOL(symbol) += info->kaslr_offset; \
23ef29
 } while (0)
23ef29
 #define WRITE_SYMBOL(str_symbol, symbol) \
23ef29
 do { \
23ef29
@@ -495,6 +499,7 @@ do { \
23ef29
 #define STR_CONFIG_X86_PAE	"CONFIG_X86_PAE=y"
23ef29
 #define STR_CONFIG_PGTABLE_4	"CONFIG_PGTABLE_4=y"
23ef29
 #define STR_CONFIG_PGTABLE_3	"CONFIG_PGTABLE_3=y"
23ef29
+#define STR_KERNELOFFSET	"KERNELOFFSET="
23ef29
 
23ef29
 /*
23ef29
  * common value
23ef29
@@ -838,6 +843,7 @@ int get_xen_info_arm64(void);
23ef29
 #define get_phys_base()		get_phys_base_arm64()
23ef29
 #define get_machdep_info()	get_machdep_info_arm64()
23ef29
 #define get_versiondep_info()	get_versiondep_info_arm64()
23ef29
+#define get_kaslr_offset(X)	FALSE
23ef29
 #define get_xen_basic_info_arch(X) get_xen_basic_info_arm64(X)
23ef29
 #define get_xen_info_arch(X) get_xen_info_arm64(X)
23ef29
 #define is_phys_addr(X)		stub_true_ul(X)
23ef29
@@ -851,6 +857,7 @@ unsigned long long vaddr_to_paddr_arm(unsigned long vaddr);
23ef29
 #define get_phys_base()		get_phys_base_arm()
23ef29
 #define get_machdep_info()	get_machdep_info_arm()
23ef29
 #define get_versiondep_info()	stub_true()
23ef29
+#define get_kaslr_offset(X)	FALSE
23ef29
 #define vaddr_to_paddr(X)	vaddr_to_paddr_arm(X)
23ef29
 #define is_phys_addr(X)		stub_true_ul(X)
23ef29
 #endif /* arm */
23ef29
@@ -863,11 +870,13 @@ unsigned long long vaddr_to_paddr_x86(unsigned long vaddr);
23ef29
 #define get_phys_base()		stub_true()
23ef29
 #define get_machdep_info()	get_machdep_info_x86()
23ef29
 #define get_versiondep_info()	get_versiondep_info_x86()
23ef29
+#define get_kaslr_offset(X)	FALSE
23ef29
 #define vaddr_to_paddr(X)	vaddr_to_paddr_x86(X)
23ef29
 #define is_phys_addr(X)		stub_true_ul(X)
23ef29
 #endif /* x86 */
23ef29
 
23ef29
 #ifdef __x86_64__
23ef29
+unsigned long get_kaslr_offset_x86_64(unsigned long vaddr);
23ef29
 int get_phys_base_x86_64(void);
23ef29
 int get_machdep_info_x86_64(void);
23ef29
 int get_versiondep_info_x86_64(void);
23ef29
@@ -876,6 +885,7 @@ unsigned long long vtop4_x86_64(unsigned long vaddr);
23ef29
 #define get_phys_base()		get_phys_base_x86_64()
23ef29
 #define get_machdep_info()	get_machdep_info_x86_64()
23ef29
 #define get_versiondep_info()	get_versiondep_info_x86_64()
23ef29
+#define get_kaslr_offset(X)	get_kaslr_offset_x86_64(X)
23ef29
 #define vaddr_to_paddr(X)	vtop4_x86_64(X)
23ef29
 #define is_phys_addr(X)		stub_true_ul(X)
23ef29
 #endif /* x86_64 */
23ef29
@@ -888,6 +898,7 @@ unsigned long long vaddr_to_paddr_ppc64(unsigned long vaddr);
23ef29
 #define get_phys_base()		stub_true()
23ef29
 #define get_machdep_info()	get_machdep_info_ppc64()
23ef29
 #define get_versiondep_info()	get_versiondep_info_ppc64()
23ef29
+#define get_kaslr_offset(X)	FALSE
23ef29
 #define vaddr_to_paddr(X)	vaddr_to_paddr_ppc64(X)
23ef29
 #define is_phys_addr(X)		stub_true_ul(X)
23ef29
 #endif          /* powerpc64 */
23ef29
@@ -899,6 +910,7 @@ unsigned long long vaddr_to_paddr_ppc(unsigned long vaddr);
23ef29
 #define get_phys_base()		stub_true()
23ef29
 #define get_machdep_info()	get_machdep_info_ppc()
23ef29
 #define get_versiondep_info()	stub_true()
23ef29
+#define get_kaslr_offset(X)	FALSE
23ef29
 #define vaddr_to_paddr(X)	vaddr_to_paddr_ppc(X)
23ef29
 #define is_phys_addr(X)		stub_true_ul(X)
23ef29
 #endif          /* powerpc32 */
23ef29
@@ -911,6 +923,7 @@ int is_iomem_phys_addr_s390x(unsigned long addr);
23ef29
 #define get_phys_base()		stub_true()
23ef29
 #define get_machdep_info()	get_machdep_info_s390x()
23ef29
 #define get_versiondep_info()	stub_true()
23ef29
+#define get_kaslr_offset(X)	FALSE
23ef29
 #define vaddr_to_paddr(X)	vaddr_to_paddr_s390x(X)
23ef29
 #define is_phys_addr(X)		is_iomem_phys_addr_s390x(X)
23ef29
 #endif          /* s390x */
23ef29
@@ -923,6 +936,7 @@ unsigned long long vaddr_to_paddr_ia64(unsigned long vaddr);
23ef29
 #define get_machdep_info()	get_machdep_info_ia64()
23ef29
 #define get_phys_base()		get_phys_base_ia64()
23ef29
 #define get_versiondep_info()	stub_true()
23ef29
+#define get_kaslr_offset(X)	FALSE
23ef29
 #define vaddr_to_paddr(X)	vaddr_to_paddr_ia64(X)
23ef29
 #define VADDR_REGION(X)		(((unsigned long)(X)) >> REGION_SHIFT)
23ef29
 #define is_phys_addr(X)		stub_true_ul(X)
23ef29
@@ -1152,6 +1166,7 @@ struct DumpInfo {
23ef29
 	int		vmemmap_psize;
23ef29
 	int		vmemmap_cnt;
23ef29
 	struct ppc64_vmemmap	*vmemmap_list;
23ef29
+	unsigned long	kaslr_offset;
23ef29
 
23ef29
 	/*
23ef29
 	 * page table info for ppc64
23ef29
@@ -1803,6 +1818,7 @@ struct memory_range {
23ef29
 struct memory_range crash_reserved_mem[CRASH_RESERVED_MEM_NR];
23ef29
 int crash_reserved_mem_nr;
23ef29
 
23ef29
+unsigned long read_vmcoreinfo_symbol(char *str_symbol);
23ef29
 int readmem(int type_addr, unsigned long long addr, void *bufptr, size_t size);
23ef29
 int get_str_osrelease_from_vmlinux(void);
23ef29
 int read_vmcoreinfo_xen(void);
23ef29
-- 
23ef29
2.9.3
23ef29