Hello Pratyush,

>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);

When will this data written to VMCOREINFO file be used ?
info->kaslr_offset is necessary for vmlinux but -x and -i are exclusive.

Thanks,
Atsushi Kumagai

>+      /*
>        * write 1st kernel's OSRELEASE
>        */
>       fprintf(info->file_vmcoreinfo, "%s%s\n", STR_OSRELEASE,
>@@ -3782,6 +3789,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 +3880,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 +8685,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 +11077,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.h b/makedumpfile.h
>index e32e567018f6..9f16becadd55 100644
>--- a/makedumpfile.h
>+++ b/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
>



_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to