[Crash-utility] [ARM64][patch v2] Auto calculate kimage_voffset by kaslr offset

Dave Anderson anderson at redhat.com
Wed Mar 15 15:27:23 UTC 2017


> 
> ----- Original Message -----
> > Hi Dave,
> > 
> > In my develop enviroment, kaslr offset will be stored in SoC on-chip memory
> > for debuging, but crash utility is not work if i only set kaslr offset by
> > command '--kaslr XXX', it also need correct kimage_voffset.
> > 
> > error message without the patch:
> > 
> > VA_BITS: 39
> > using 40000000 as phys_offset
> > kimage_voffset: 0
> > phys_offset: 40000000
> > .....cut....
> > <readmem: ffffff9381e074a0, KVADDR, "cpu_possible_mask", 8, (FOE),
> > 7fffce0dfa48>
> > <read_ramdump: addr: ffffff9381e074a0 paddr: 13b9e074a0 cnt: 8>
> > read_ramdump: READ_ERROR: offset not found for paddr: 13b9e074a0
> > crash: read error: kernel virtual address: ffffff9381e074a0 type:
> > "cpu_possible_mask"
> > 
> > This patch add a function to auto calculate kimage_voffset by kaslr offset.
> > Please review it.
> > 
> > Thanks,
> > Yueyi Li
> > Hello Yueyi,
> > 
> > I have a few questions about this patch.
> > 
> > First, can you clarify the kernel version and the dumpfile type that
> > you are trying to address?
> > 
> > I understand the confusion, given that arm64 kdump/KASLR support is still being
> > debated upstream.  Eventually, arm64 kdump-generated dumpfiles will have
> > "NUMBER(kimage_voffset)" and "NUMBER(PHYS_OFFSET)" VMCOREINFO entries, which
> > will simplify things significantly (and you can see that the crash utility
> > already has support for them in advance).
> Actually, i use crash utility to analysis Android device crash, Linux kernel version is 4.4. The ramdump file is not generated by kdump, it is whole DDR SDRAM snapshot collected by another RTOS, so i don`t have vmcoreinfo to get kimage_voffset & phys_offset. I my opinion, only set kaslr offset should work well even if without vmcore file and kimage_voffse, it looks more reasonable.
> > It seems that this patch would only be applicable when looking at an ELF
> > dumpfile, given that your arch_calc_kimage_voffset() function calls
> > arm_kdump_phys_base() -- which only applies if you are looking at an
> > ELF dumpfile:
> > 
> > +static void
> > +arm64_calc_kimage_voffset(void)
> > +{
> > +       struct machine_specific *ms = machdep->machspec;
> > +       ulong kimage_offset;
> > +       ulong phys_offset;
> > +       struct syment *sp;
> > +
> > +       if (machdep->flags & KIMG_VOFFSET) /* --machdep override */
> > +               return;
> > +
> > +       if ((kt->flags2 & KASLR) && (kt->flags & RELOC_SET)){
> > +               arm_kdump_phys_base(&phys_offset);
> > +               ms->kimage_voffset = ms->vmalloc_start_addr + (kt->relocate * -1) - phys_offset;
> > +       }
> > +
> > +}
> > 
> > Is that correct?  And if so, why not call arm64_kdump_phys_base() instead?
> > Because I see in your "error message without the patch" above, the phys_base 
> > seems to have been calculated correctly to be 40000000, so it looks like the 
> > call from arm64_calc_phys_offset() to arm64_kdump_phys_base() must have worked.
> > (since arm64_kdump_phys_base() ultimately calls arm_kdump_phys_base() if nothing
> > else works) 
> > 
> > So what would happen if you called arm64_calc_phys_offset() *before* your new
> > function?  Wouldn't it correctly determine phys_offset?  And then there would
> > be no need for you to call it in your new function:
> > 
> > @@ -324,6 +325,9 @@ arm64_init(int when)
> >                 machdep->init_kernel_pgd = arm64_init_kernel_pgd;
> > 
> >                 /* use machdep parameters */
> > +               arm64_calc_kimage_voffset();
> > +
> > +               /* use machdep parameters */
> >                 arm64_calc_phys_offset();
> When kernel ASLR is enabled on arm64, the kernel image start address
> can be randomized, phys_offset is no more equal the start address of
> first memory block. It means, arm_kdump_phys_base() can not calculate
> correctly address, we need kimage_voffset to calculate correctly 
> phys_offset, this is what arm64_calc_phys_offset() to do( just on 
> live system & ELF ramdump). So arm64_calc_kimage_voffset() should be
> called first. This is why crash utility is not work if '-m kimage_voffset'
> is not given.
> 
> debug log with the patch, kaslr offset is 0x1378e00000, start address of first memory block is 0x40000000:
> readmem: read_ramdump()                                                                   
> VA_BITS: 39                                                                               
> using ffffffd340000000 as phys_offset                                                     
> kimage_voffset: ffffff9340e00000                                                          
> phys_offset: ffffffd340000000                                                             
> gdb vmlinux                                                                               
> GNU gdb (GDB) 7.6                                                                         
> Copyright (C) 2013 Free Software Foundation, Inc.                                         
> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>             
> This is free software: you are free to change and redistribute it.                        
> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"                
> and "show warranty" for details.                                                          
> This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=aarch64-elf-linux"...
>                                                                                           
> cpu_possible_mask: cpus: 0 1 2 3 4 5 6 7                                                  
>  cpu_present_mask: cpus: 0 1 2 3 4 5 6 7                                                  
>   cpu_online_mask: cpus: 0 1 2 3 4 5 6                                                    
>   cpu_active_mask: cpus: 0 1 2 3 4 5 6                                                    
> xtime timespec.tv_sec: 58c27009: Fri Mar 10 17:21:13 2017                                 
> utsname:                                                                                  
>      sysname: Linux                                                                       
>     nodename: localhost                                                                   
>      release: 4.4.21-perf-g5ec6736-00564-gbdc7dcf                                         
>      version: #1 SMP PREEMPT Wed Mar 8 23:02:12 CST 2017                                  
>      machine: aarch64                                                                     
>   domainname: localdomain                                                                 
> 
> > In addition, arm64_calc_phys_offset() also tries to determine the phys_offset value
> > for compressed kdump dumpfiles and live systems.  If the dumpfile has been
> > compressed (by the makedumpfile facility), or if you are running on a live system,
> > then your patch would fail to determine phys_offset.  But if you were to call 
> > arm64_calc_phys_offset() instead, it would call diskdump_phys_base() for compressed
> > dumpfiles, or try to determine the phys_offset value from /proc/iomem on live
> > systems.
> > 
> > Dave
> > 
> > 
> I'm not familar with compressed dumpfiles, just add a judgment in my function. 
> For live system, if kimage_voffset has been calculated, arm64_calc_phys_offset 
> will use it calculate correctly phys_offset instead of read from /proc/iomem.
> 
>         if ((machdep->flags & NEW_VMEMMAP) &&
>             ms->kimage_voffset && (sp = kernel_symbol_search("memstart_addr"))) {
>             paddr =    sp->value - machdep->machspec->kimage_voffset;
>             if (READMEM(pc->mfd, &phys_offset, sizeof(phys_offset),
>                 sp->value, paddr) > 0) {
>                 ms->phys_offset = phys_offset;
>                 return;
>             }
>         }
> 
> I have attached patch v2, Could you please review it?
> 
> Thanks,
> Yueyi Li
> From 10d9a7879589888c8ffe24e8245062115dc16f1e Mon Sep 17 00:00:00 2001
> From: Yueyi Li <liyueyi live com>
> Date: Tue, 14 Mar 2017 21:25:21 +0800
> Subject: [PATCH] [ARM64][patch] Auto calculate kimage_voffset by kaslr offset
> 
> ARM64 kimage_voffset can be calculated if kernel ASLR offset is known.
> Add a function to auto calculate kimage_voffset when '--kaslr=<offset>'
> was set.
> ---
>  arm64.c | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/arm64.c b/arm64.c
> index 6eaf96d..b51b826 100644
> --- a/arm64.c
> +++ b/arm64.c
> @@ -27,6 +27,7 @@
>  static struct machine_specific arm64_machine_specific = { 0 };
>  static int arm64_verify_symbol(const char *, ulong, char);
>  static void arm64_parse_cmdline_args(void);
> +static void arm64_calc_kimage_voffset(void);
>  static void arm64_calc_phys_offset(void);
>  static void arm64_calc_virtual_memory_ranges(void);
>  static int arm64_kdump_phys_base(ulong *);
> @@ -324,6 +325,9 @@ arm64_init(int when)
>  		machdep->init_kernel_pgd = arm64_init_kernel_pgd;
>  
>  		/* use machdep parameters */
> +		arm64_calc_kimage_voffset();
> +
> +		/* use machdep parameters */
>  		arm64_calc_phys_offset();
>  	
>  		if (CRASHDEBUG(1)) {
> @@ -735,6 +739,23 @@ arm64_parse_cmdline_args(void)
>  	}
>  }
>  
> +static void
> +arm64_calc_kimage_voffset(void)
> +{
> +	struct machine_specific *ms = machdep->machspec;
> +	ulong phys_offset;
> +
> +	if (ms->kimage_voffset) /* vmcoreinfo or --machdep override */
> +		return;
> +
> +	if (DISKDUMP_DUMPFILE())
> +		return;
> +	else if ((kt->flags2 & KASLR) && (kt->flags & RELOC_SET)){
> +		arm_kdump_phys_base(&phys_offset);    /*get start address of first memory block*/
> +		ms->kimage_voffset = ms->vmalloc_start_addr + (kt->relocate * -1) - phys_offset;
> +	}
> +
> +}

In addition to DISKUMP_DUMPFILE(), it also needs to return on live systems 
and any other dumpfile type.  I need to see your pc->flags and pc->flags2
settings to see how your dumpfile is recognized -- what do you see when you
run this command against your RAM dump?:

  crash> help -p | grep -A3 " flags:" | head -3
              flags: 1010000210c06 
            (RUNTIME|TTY|HASH|SCROLL|GDB_INIT|READLINE|KDUMP|DATADEBUG)           
             flags2: 100400 (VMCOREINFO|REDZONE)
  crash> 

Thanks,
  Dave




More information about the Crash-utility mailing list