[Crash-utility] [PATCH 3/3] Fix a KASLR problem of sadump

Hatayama, Daisuke d.hatayama at jp.fujitsu.com
Thu Oct 12 08:11:38 UTC 2017



> -----Original Message-----
> From: Takao Indoh [mailto:indou.takao at jp.fujitsu.com]
> Sent: Tuesday, October 10, 2017 6:26 PM
> To: crash-utility at redhat.com; Hatayama, Daisuke 
> <d.hatayama at jp.fujitsu.com>
> Subject: [PATCH 3/3] Fix a KASLR problem of sadump
> 
> This patch fix a problem that crash cannot open a dumpfile which can be
> captured by sadump in KASLR enabled kernel.
> 
> The sadump dumpfile has register information in the header, therefore
> this problem can be solved by the same way as virsh dump.
> 
> Signed-off-by: Takao Indoh <indou.takao at jp.fujitsu.com>
> ---
>  defs.h    |  3 +++
>  netdump.c |  3 +++
>  sadump.c  | 60
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  sadump.h  |  4 ++++
>  symbols.c | 10 ++++++----
>  5 files changed, 75 insertions(+), 5 deletions(-)
> 
> diff --git a/defs.h b/defs.h
> index 558ab7b..2c84d73 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -6263,12 +6263,15 @@ FILE *set_sadump_fp(FILE *);
>  void get_sadump_regs(struct bt_info *bt, ulong *ipp, ulong *spp);
>  void sadump_display_regs(int, FILE *);
>  int sadump_phys_base(ulong *);
> +int sadump_set_phys_base(ulong);
>  void sadump_show_diskset(void);
>  int sadump_is_zero_excluded(void);
>  void sadump_set_zero_excluded(void);
>  void sadump_unset_zero_excluded(void);
>  struct sadump_data;
>  struct sadump_data *get_sadump_data(void);
> +ulong sadump_get_idtr(void);
> +ulong sadump_get_cr3(void);
> 
>  /*
>   * qemu.c
> diff --git a/netdump.c b/netdump.c
> index b03ba13..b0ce160 100644
> --- a/netdump.c
> +++ b/netdump.c
> @@ -5132,6 +5132,9 @@ calc_kaslr_offset(ulong *kaslr_offset, ulong
> *phys_base)
>  	if (vmcore_kaslr_check()) {
>  		idtr = qemu_get_idtr();
>  		cr3 = qemu_get_cr3();
> +	} else if (SADUMP_DUMPFILE()) {
> +		idtr = sadump_get_idtr();
> +		cr3 = sadump_get_cr3();
>  	} else
>  		return FALSE;
> 
> diff --git a/sadump.c b/sadump.c
> index a96ba9c..d2a5c47 100644
> --- a/sadump.c
> +++ b/sadump.c
> @@ -1558,15 +1558,27 @@ sadump_display_regs(int cpu, FILE *ofp)
>   */
>  int sadump_phys_base(ulong *phys_base)
>  {
> -	if (SADUMP_VALID()) {
> +	if (SADUMP_VALID() && !sd->phys_base) {
>  		if (CRASHDEBUG(1))
>  			error(NOTE, "sadump: does not save phys_base.\n");
>  		return FALSE;
>  	}
> 
> +	if (sd->phys_base) {
> +		*phys_base = sd->phys_base;
> +		return TRUE;
> +	}
> +
>  	return FALSE;
>  }
> 
> +int sadump_set_phys_base(ulong phys_base)
> +{
> +	sd->phys_base = phys_base;
> +
> +	return TRUE;
> +}
> +
>  /*
>   *  Used by "sys" command to show diskset disk names.
>   */
> @@ -1649,3 +1661,49 @@ get_sadump_data(void)
>  {
>  	return sd;
>  }
> +
> +static int
> +get_sadump_smram_cpu_state_any(struct sadump_smram_cpu_state *smram)
> +{
> +	ulong offset;
> +	struct sadump_header *sh = sd->dump_header;
> +	int apicid;
> +	struct sadump_smram_cpu_state scs, zero;
> +
> +	offset = sd->sub_hdr_offset + sizeof(uint32_t) +
> +		 sd->dump_header->nr_cpus * sizeof(struct
> sadump_apic_state);
> +
> +	memset(&zero, 0, sizeof(zero));
> +
> +	for (apicid = 0; apicid < sh->nr_cpus; ++apicid) {
> +		if (!read_device(&scs, sizeof(scs), &offset)) {
> +			error(INFO, "sadump: cannot read sub header "
> +			      "cpu_state\n");
> +			return FALSE;
> +		}
> +		if (memcmp(&scs, &zero, sizeof(scs)) != 0) {
> +			*smram = scs;
> +			return TRUE;
> +		}
> +	}
> +
> +	return FALSE;
> +}
> +
> +ulong
> +sadump_get_idtr(void)
> +{
> +	struct sadump_smram_cpu_state scs;
> +	get_sadump_smram_cpu_state_any(&scs);
> +
> +	return ((uint64_t)scs.IdtUpper)<<32 | (uint64_t)scs.IdtLower;
> +}

This returns physical address so should have type physaddr_t in meaning.

Also, I like:

physaddr_t
sadump_get_idtr(void)
{
        struct sadump_smram_cpu_state scs;

        get_sadump_smram_cpu_state_any(&scs);
        return ((uint64_t)scs.IdtUpper)<<32 | (uint64_t)scs.IdtLower;
}

> +
> +ulong
> +sadump_get_cr3(void)
> +{
> +	struct sadump_smram_cpu_state scs;
> +	get_sadump_smram_cpu_state_any(&scs);
> +
> +	return scs.Cr3;
> +}

Just as the above comment:

ulong
sadump_get_cr3(void)
{
    struct sadump_smram_cpu_state scs;

    get_sadump_smram_cpu_state_any(&scs);
    return scs.Cr3;
}

> diff --git a/sadump.h b/sadump.h
> index 7f8e384..66aa17e 100644
> --- a/sadump.h
> +++ b/sadump.h
> @@ -219,6 +219,10 @@ struct sadump_data {
>  	ulonglong backup_offset;
> 
>  	uint64_t max_mapnr;
> +
> +	ulong kaslr_offset;
> +	ulong phys_base;
> +	ulong cr3;
>  };
> 
>  struct sadump_data *sadump_get_sadump_data(void);
> diff --git a/symbols.c b/symbols.c
> index 9e0c9df..38720b5 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -625,7 +625,7 @@ kaslr_init(void)
>  		}
>  	}
> 
> -	if (vmcore_kaslr_check())
> +	if (vmcore_kaslr_check() || SADUMP_DUMPFILE())
>  		kt->flags2 |= KASLR_CHECK;
>  }
> 
> @@ -640,7 +640,7 @@ derive_kaslr_offset(bfd *abfd, int dynamic, bfd_byte
> *start, bfd_byte *end,
>  	unsigned long relocate;
>  	ulong _stext_relocated;
> 
> -	if (vmcore_kaslr_check()) {
> +	if (vmcore_kaslr_check() || SADUMP_DUMPFILE()) {
>  		ulong kaslr_offset = 0, phys_base = 0;
> 
>  		calc_kaslr_offset(&kaslr_offset, &phys_base);
> @@ -650,8 +650,10 @@ derive_kaslr_offset(bfd *abfd, int dynamic, bfd_byte
> *start, bfd_byte *end,
>  			kt->flags |= RELOC_SET;
>  		}
> 
> -		if (phys_base)
> +		if (phys_base) {
>  			kdump_set_phys_base(phys_base);
> +			sadump_set_phys_base(phys_base);
> +		}
> 
>  		return;
>  	}
> @@ -12255,7 +12257,7 @@ numeric_forward(const void *P_x, const void *P_y)
>  		}
>  	}
> 
> -	if (vmcore_kaslr_check()) {
> +	if (vmcore_kaslr_check() || SADUMP_DUMPFILE()) {
>  		if (STREQ(x->name, "divide_error"))
>  			st->divide_error_vmlinux = valueof(x);
>  		else if (STREQ(y->name, "divide_error"))
> --
> 2.9.5





More information about the Crash-utility mailing list