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