[Crash-utility] [PATCH] Obtain KASLR offset from early S390X dumps

Dave Anderson anderson at redhat.com
Mon Nov 25 19:00:23 UTC 2019



----- Original Message -----
> 
> ----- Original Message -----
> > If the kernel crashes before vmcoreinfo initialization, there is
> > no way to extract KASLR offset for such early s390 dumps.
> > With a new s390 kernel patch, the KASLR offset will be stored in the
> > lowcore
> > memory during early boot and then overwritten after vmcoreinfo is
> > initialized.
> > This patch allows crash to identify the KASLR offset stored in lowcore
> > memory for s390 dumps.
> > 
> > Signed-off-by: Mikhail Zaslonko <zaslonko at linux.ibm.com>
> > ---
> >  s390x.c | 21 +++++++++++++++++++++
> >  1 file changed, 21 insertions(+)
> > 
> > diff --git a/s390x.c b/s390x.c
> > index 4a1a466..d2c6702 100644
> > --- a/s390x.c
> > +++ b/s390x.c
> > @@ -46,6 +46,8 @@
> >  
> >  #define S390X_PSW_MASK_PSTATE	0x0001000000000000UL
> >  
> > +#define S390X_LC_VMCORE_INFO	0xe0c
> > +
> >  /*
> >   * Flags for Region and Segment table entries.
> >   */
> > @@ -460,6 +462,8 @@ static void s390x_check_live(void)
> >  void
> >  s390x_init(int when)
> >  {
> > +	ulong s390x_lc_kaslr;
> > +
> >  	switch (when)
> >  	{
> >  	case SETUP_ENV:
> > @@ -486,6 +490,23 @@ s390x_init(int when)
> >  		machdep->verify_paddr = generic_verify_paddr;
> >  		machdep->get_kvaddr_ranges = s390x_get_kvaddr_ranges;
> >  		machdep->ptrs_per_pgd = PTRS_PER_PGD;
> > +		if (!(kt->flags & RELOC_SET)) {
> > +			/* Read the value from well-known lowcore location*/
> > +			readmem(S390X_LC_VMCORE_INFO, PHYSADDR, &s390x_lc_kaslr,
> > +				sizeof(s390x_lc_kaslr), "s390x_lc_kaslr",
> > +				FAULT_ON_ERROR);
> > +			/* Check for explicit kaslr offset flag */
> > +			if (s390x_lc_kaslr & 0x1UL) {
> > +				/* Drop the last bit to get an offset value */
> > +				s390x_lc_kaslr &= ~(0x1UL);
> > +				/* Make sure that the offset is aligned by 0x1000 */
> > +				if (s390x_lc_kaslr && !(s390x_lc_kaslr & 0xfff)) {
> > +					kt->relocate = s390x_lc_kaslr * (-1);
> > +					kt->flags |= RELOC_SET;
> > +					kt->flags2 |= KASLR;
> > +				}
> > +			}
> > +		}
> >  		break;
> >  
> >  	case PRE_GDB:
> > --
> 
> Hi Mikhail,
>  
> Your patch fails on a live system that utilizes /proc/kcore as the memory
> source:
> 
>   # ./crash
> 
>   crash 7.2.7++
>   Copyright (C) 2002-2019  Red Hat, Inc.
>   Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
>   Copyright (C) 1999-2006  Hewlett-Packard Co
>   Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
>   Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
>   Copyright (C) 2005, 2011  NEC Corporation
>   Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
>   Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
>   This program is free software, covered by the GNU General Public License,
>   and you are welcome to change it and/or distribute copies of it under
>   certain conditions.  Enter "help copying" to see the conditions.
>   This program has absolutely no warranty.  Enter "help warranty" for
>   details.
>  
>   crash: read error: physical address: e0c  type: "s390x_lc_kaslr"
>   #
> 
> That's because the newly-introduced readmem() becomes the very first memory
> read access, and because you call readmem() with PHYSADDR and FAULT_ON_ERROR,
> you don't allow crash to pivot from /dev/mem to /proc/kcore when it does its
> first KVADDR readmem() later on during initialization:
> 
>   # ./crash -d4
>   ... [ cut ] ...
>      
>   readmem: read_dev_mem() -> /dev/mem
>   <readmem: e0c, PHYSADDR, "s390x_lc_kaslr", 8, (FOE), 3fffbf7e848>
>   <read_dev_mem: addr: e0c paddr: e0c cnt: 8>
>   /dev/mem: Operation not permitted
>   crash: read(/dev/mem, e0c, 8): -1 (ffffffffffffffff)
>   crash: read error: physical address: e0c  type: "s390x_lc_kaslr"
>   #
> 
> Also, if there is *ever* a chance that the readmem() could fail to read
> that physical address from a dumpfile, I would also suggest that you allow
> it to fail quietly by changing the readmem() flag from FAULT_ON_ERROR
> to QUIET|RETURN_ON_ERROR like this:
> 
>                         /* Read the value from well-known lowcore location*/
>                         if (readmem(S390X_LC_VMCORE_INFO, PHYSADDR,
>                         &s390x_lc_kaslr,
>                             sizeof(s390x_lc_kaslr), "s390x_lc_kaslr",
>                             QUIET|RETURN_ON_ERROR)) {
>                                 /* Check for explicit kaslr offset flag */
>                                 if (s390x_lc_kaslr & 0x1UL) {
>                                         /* Drop the last bit to get an offset
>                                         value */
>                                         s390x_lc_kaslr &= ~(0x1UL);
>                                         /* Make sure that the offset is
>                                         aligned by 0x1000 */
>                                         if (s390x_lc_kaslr &&
>                                         !(s390x_lc_kaslr & 0xfff)) {
>                                                 kt->relocate = s390x_lc_kaslr
>                                                 * (-1);
>                                                 kt->flags |= RELOC_SET;
>                                                 kt->flags2 |= KASLR;
>                                         }
>                                 }
>                         }
> 
> Thanks,
>   Dave

I meant to add that given this is only relevant to dumpfiles, you
could avoid the whole /dev/mem-/proc/kcore live system issue by gating
your patch like this:

                if (DUMPFILE() && !(kt->flags & RELOC_SET)) {


Dave




More information about the Crash-utility mailing list