Blob Blame History Raw
From 616c98d1abac6f348f13cfe55e2df5e1d5d26781 Mon Sep 17 00:00:00 2001
From: Bhupesh Sharma <bhsharma@redhat.com>
Date: Thu, 19 Jul 2018 11:13:41 +0530
Subject: [PATCH] [PATCH] arm64: 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 31 -x vmlinux --config scrub.conf vmcore dumpfile_{1,2,3}
  readpage_elf: Attempt to read non-existent page at 0xffffa8a5bf180000.
  readmem: type_addr: 1, addr:ffffa8a5bf180000, size:8
  vaddr_to_paddr_arm64: Can't read pgd
  readmem: Can't convert a virtual address(ffff0000092a542c) to physical
  address.
  readmem: type_addr: 0, addr:ffff0000092a542c, 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 (I checked this with kernel 4.18.0-rc4+):

  # makedumpfile --split -d 31 -x vmlinux --config scrub.conf vmcore dumpfile_{1,2,3}
  The kernel version is not supported.
  The makedumpfile operation may be incomplete.
  Checking for memory holes                         : [100.0 %] \
  Checking for memory holes                         : [100.0 %] |
  Checking foExcluding unnecessary pages                       : [100.0 %]
  \
  Excluding unnecessary pages                       : [100.0 %] \

  The dumpfiles are saved to dumpfile_1, dumpfile_2, and dumpfile_3.

  makedumpfile Completed.

This feature also requires a fix in the kernel as well which has been submitted
upstream (see[0]).

[0] https://patchwork.kernel.org/patch/10533333/

Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
---
 arch/arm64.c   | 41 +++++++++++++++++++++++++++++++++++++++++
 makedumpfile.h |  3 ++-
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/makedumpfile-1.6.4/arch/arm64.c b/makedumpfile-1.6.4/arch/arm64.c
index 836ce17b339c..362609668ea2 100644
--- a/makedumpfile-1.6.4/arch/arm64.c
+++ b/makedumpfile-1.6.4/arch/arm64.c
@@ -181,6 +181,47 @@ get_phys_base_arm64(void)
	return TRUE;
 }

+unsigned long
+get_kaslr_offset_arm64(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);
+				DEBUG_MSG("info->kaslr_offset: %lx\n", info->kaslr_offset);
+			}
+		}
+	}
+
+	if (vaddr >= __START_KERNEL_map &&
+			vaddr < __START_KERNEL_map + info->kaslr_offset) {
+		DEBUG_MSG("info->kaslr_offset: %lx\n", 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;
+	}
+}
+
 ulong
 get_stext_symbol(void)
 {
diff --git a/makedumpfile-1.6.4/makedumpfile.h b/makedumpfile-1.6.4/makedumpfile.h
index ba85f03e856d..3244d31ae43a 100644
--- a/makedumpfile-1.6.4/makedumpfile.h
+++ b/makedumpfile-1.6.4/makedumpfile.h
@@ -971,12 +971,13 @@ unsigned long long vaddr_to_paddr_arm64(unsigned long vaddr);
 int get_versiondep_info_arm64(void);
 int get_xen_basic_info_arm64(void);
 int get_xen_info_arm64(void);
+unsigned long get_kaslr_offset_arm64(unsigned long vaddr);
 #define find_vmemmap()		stub_false()
 #define vaddr_to_paddr(X)	vaddr_to_paddr_arm64(X)
 #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)	stub_false()
+#define get_kaslr_offset(X)	get_kaslr_offset_arm64(X)
 #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)
--
2.7.4