> -----Original Message----- > From: HATAYAMA Daisuke <d.hatayama@xxxxxxxxxxxxxx> > > We faced recently a memory dump collected by sadump where unused part > of register values are non-zero. For the crash dump, calculating > kaslr_offset fails because it is based on the assumption that unused > part of register values in the sadump format are always zero cleared. > > The problem is that used and unused part of register values are > rigorously indistinguishable in the sadump format. Although there is > kernel data structure that represents a map between logical cpu > numbers and lapic ids, they cannot be used in order to calculate > kaslr_offset. > > To fix this, we have no choice but use a trial-and-error approach: try > to use each entry of register values in order until we find a good > pair of cr3 and idtr by which we can refer to linux_banner symbol as > expected. > > This fix is for the sadump specific issue, so there is no functional > change for the other crash dump formats. > --- > kaslr_helper.c | 39 +++++++++++++++++++++++++++++++++++---- > sadump.c | 18 +++++++++++------- > 2 files changed, 46 insertions(+), 11 deletions(-) > > diff --git a/kaslr_helper.c b/kaslr_helper.c > index acbb5c2..bb19e54 100644 > --- a/kaslr_helper.c > +++ b/kaslr_helper.c > @@ -406,6 +406,7 @@ calc_kaslr_offset(ulong *ko, ulong *pb) > if (!machine_type("X86_64")) > return FALSE; > > +retry: > if (SADUMP_DUMPFILE()) { > if (!sadump_get_cr3_idtr(&cr3, &idtr)) > return FALSE; > @@ -437,12 +438,20 @@ calc_kaslr_offset(ulong *ko, ulong *pb) > machdep->machspec->pgdir_shift = PGDIR_SHIFT; > machdep->machspec->ptrs_per_pgd = PTRS_PER_PGD; > if (!readmem(pgd, PHYSADDR, machdep->pgd, PAGESIZE(), > - "pgd", RETURN_ON_ERROR)) > - goto quit; > + "pgd", RETURN_ON_ERROR)) { > + if (SADUMP_DUMPFILE()) > + goto retry; > + else > + goto quit; > + } > > /* Convert virtual address of IDT table to physical address */ > - if (!kvtop(NULL, idtr, &idtr_paddr, verbose)) > - goto quit; > + if (!kvtop(NULL, idtr, &idtr_paddr, verbose)) { > + if (SADUMP_DUMPFILE()) > + goto retry; > + else > + goto quit; > + } > > /* Now we can calculate kaslr_offset and phys_base */ > divide_error_vmcore = get_vec0_addr(idtr_paddr); > @@ -450,6 +459,28 @@ calc_kaslr_offset(ulong *ko, ulong *pb) > phys_base = idtr_paddr - > (st->idt_table_vmlinux + kaslr_offset - __START_KERNEL_map); > > + if (SADUMP_DUMPFILE()) { > + char buf[sizeof("Linux version")]; > + ulong linux_banner_paddr; > + > + if (!kvtop(NULL, > + st->linux_banner_vmlinux + kaslr_offset, > + &linux_banner_paddr, > + verbose)) > + goto retry; > + > + if (!readmem(linux_banner_paddr, > + PHYSADDR, > + buf, > + sizeof(buf), > + "linux_banner", > + RETURN_ON_ERROR)) > + goto retry; > + > + if (!STRNEQ(buf, "Linux version")) > + goto retry; > + } > + > if (CRASHDEBUG(1)) { > fprintf(fp, "calc_kaslr_offset: idtr=%lx\n", idtr); > fprintf(fp, "calc_kaslr_offset: pgd=%lx\n", pgd); > diff --git a/sadump.c b/sadump.c > index 35f7cf0..85b4a09 100644 > --- a/sadump.c > +++ b/sadump.c > @@ -1666,21 +1666,24 @@ get_sadump_smram_cpu_state_any(struct sadump_smram_cpu_state *smram) > { > ulong offset; > struct sadump_header *sh = sd->dump_header; > - int apicid; > + static int apicid; > struct sadump_smram_cpu_state scs, zero; $ make clean $ make warn ... cc -c -g -DX86_64 -DSNAPPY -DLZO -DGDB_7_6 sadump.c -Wall -O2 -Wstrict-prototypes -Wmissing-prototypes -fstack-protector -Wformat-security sadump.c: In function ‘get_sadump_smram_cpu_state_any’: sadump.c:1670:44: warning: unused variable ‘zero’ [-Wunused-variable] struct sadump_smram_cpu_state scs, zero; ^ I can remove that zero when merging. > > - offset = sd->sub_hdr_offset + sizeof(uint32_t) + > - sd->dump_header->nr_cpus * sizeof(struct sadump_apic_state); > + if (apicid >= sh->nr_cpus) > + return FALSE; > > - memset(&zero, 0, sizeof(zero)); > + offset = sd->sub_hdr_offset + sizeof(uint32_t) + > + sd->dump_header->nr_cpus * sizeof(struct sadump_apic_state) + > + apicid * sizeof(scs); > > - for (apicid = 0; apicid < sh->nr_cpus; ++apicid) { > + while (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) { > + if (scs.Cr3 && (scs.IdtUpper || scs.IdtLower)) { > *smram = scs; > return TRUE; > } > @@ -1695,7 +1698,8 @@ sadump_get_cr3_idtr(ulong *cr3, ulong *idtr) > struct sadump_smram_cpu_state scs; > > memset(&scs, 0, sizeof(scs)); > - get_sadump_smram_cpu_state_any(&scs); > + if (!get_sadump_smram_cpu_state_any(&scs)) > + return FALSE; > > *cr3 = scs.Cr3; > *idtr = ((uint64_t)scs.IdtUpper)<<32 | (uint64_t)scs.IdtLower; > -- > 1.8.3.1 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility