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 <[email protected]>
---
arch/x86_64.c | 36 ++++++++++++++++++++++++++++++++++++
erase_info.c | 1 +
makedumpfile.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
makedumpfile.h | 16 ++++++++++++++++
4 files changed, 106 insertions(+)
diff --git a/arch/x86_64.c b/arch/x86_64.c
index e978a36f8878..fd2e8ac154d6 100644
--- a/arch/x86_64.c
+++ b/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/erase_info.c b/erase_info.c
index f2ba9149e93e..60abfa1a1adf 100644
--- a/erase_info.c
+++ b/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.c b/makedumpfile.c
index 301772a8820c..4986d098d69a 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -2099,6 +2099,13 @@ void
write_vmcoreinfo_data(void)
{
/*
+ * write 1st kernel's KERNELOFFSET
+ */
+ if (info->kaslr_offset)
+ fprintf(info->file_vmcoreinfo, "%s%lx\n", STR_KERNELOFFSET,
+ info->kaslr_offset);