diff --git a/SOURCES/github_b97e7fd4e826_to_8b50d94ada21.patch b/SOURCES/github_b97e7fd4e826_to_8b50d94ada21.patch new file mode 100644 index 0000000..3c9e547 --- /dev/null +++ b/SOURCES/github_b97e7fd4e826_to_8b50d94ada21.patch @@ -0,0 +1,368 @@ +From b97e7fd4e8268d5c46f1b30b41ce1f6ca9ceb216 Mon Sep 17 00:00:00 2001 +From: HATAYAMA Daisuke +Date: Mon, 27 Jul 2020 19:00:19 +0900 +Subject: [PATCH 1/4] symbols: Add linux_banner_vmlinux in symbol table + +Add linux_banner_vmlinux in symbol table, which we'll later use in +calc_kaslr_offset() to do a sanity check in calculation of +kaslr_offset and phys_base. + +Signed-off-by: HATAYAMA Daisuke +--- + defs.h | 1 + + symbols.c | 10 ++++++++++ + 2 files changed, 11 insertions(+) + +diff --git a/defs.h b/defs.h +index d7adb23b86d5..17e98763362b 100644 +--- a/defs.h ++++ b/defs.h +@@ -2714,6 +2714,7 @@ struct symbol_table_data { + ulong pti_init_vmlinux; + ulong kaiser_init_vmlinux; + int kernel_symbol_type; ++ ulong linux_banner_vmlinux; + }; + + /* flags for st */ +diff --git a/symbols.c b/symbols.c +index 3b1f08af43ff..b9de4a179d93 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -3226,6 +3226,11 @@ dump_symbol_table(void) + fprintf(fp, " kaiser_init_vmlinux: (unused)\n"); + } + ++ if (SADUMP_DUMPFILE()) ++ fprintf(fp, "linux_banner_vmlinux: %lx\n", st->linux_banner_vmlinux); ++ else ++ fprintf(fp, "linux_banner_vmlinux: (unused)\n"); ++ + fprintf(fp, " symval_hash[%d]: %lx\n", SYMVAL_HASH, + (ulong)&st->symval_hash[0]); + +@@ -12687,6 +12692,11 @@ numeric_forward(const void *P_x, const void *P_y) + else if (STREQ(y->name, "idt_table")) + st->idt_table_vmlinux = valueof(y); + ++ if (STREQ(x->name, "linux_banner")) ++ st->linux_banner_vmlinux = valueof(x); ++ else if (STREQ(y->name, "linux_banner")) ++ st->linux_banner_vmlinux = valueof(y); ++ + if (STREQ(x->name, "saved_command_line")) + st->saved_command_line_vmlinux = valueof(x); + else if (STREQ(y->name, "saved_command_line")) +-- +2.7.4 + + +From d494fabe99b90cea8d717a90951e44e6dbda84bb Mon Sep 17 00:00:00 2001 +From: HATAYAMA Daisuke +Date: Mon, 27 Jul 2020 19:00:20 +0900 +Subject: [PATCH 2/4] symbols: fix initialization of st->{pti_init, + kaiser}_vmlinux + +In numeric_forward(), care must be taken both for x- and y- positions, +but either of kaiser_init and pti_init is only for x- or y- position +only. Fix this. Also, move the code in an appropriate position +according to each symbol name in the alphabetical order. + +Signed-off-by: HATAYAMA Daisuke +--- + symbols.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/symbols.c b/symbols.c +index b9de4a179d93..2fecaee093a2 100644 +--- a/symbols.c ++++ b/symbols.c +@@ -12692,20 +12692,25 @@ numeric_forward(const void *P_x, const void *P_y) + else if (STREQ(y->name, "idt_table")) + st->idt_table_vmlinux = valueof(y); + ++ if (STREQ(x->name, "kaiser_init")) ++ st->kaiser_init_vmlinux = valueof(x); ++ else if (STREQ(y->name, "kaiser_init")) ++ st->kaiser_init_vmlinux = valueof(y); ++ + if (STREQ(x->name, "linux_banner")) + st->linux_banner_vmlinux = valueof(x); + else if (STREQ(y->name, "linux_banner")) + st->linux_banner_vmlinux = valueof(y); + ++ if (STREQ(x->name, "pti_init")) ++ st->pti_init_vmlinux = valueof(x); ++ else if (STREQ(y->name, "pti_init")) ++ st->pti_init_vmlinux = valueof(y); ++ + if (STREQ(x->name, "saved_command_line")) + st->saved_command_line_vmlinux = valueof(x); + else if (STREQ(y->name, "saved_command_line")) + st->saved_command_line_vmlinux = valueof(y); +- +- if (STREQ(x->name, "pti_init")) +- st->pti_init_vmlinux = valueof(x); +- else if (STREQ(y->name, "kaiser_init")) +- st->kaiser_init_vmlinux = valueof(y); + } + + xs = bfd_get_section(x); +-- +2.7.4 + + +From ff45c8da8cafed350940b1a56dce65f58051db5e Mon Sep 17 00:00:00 2001 +From: HATAYAMA Daisuke +Date: Mon, 27 Jul 2020 19:00:22 +0900 +Subject: [PATCH 3/4] kaslr: cleanup how to set values to the arguments of + calc_kaslr_offset() + +Setting values of the arguments of calc_kaslr_offset() should be done +at the end of the function. Currently, they are set in the middle +where their values could still be changed according to +get_kaslr_offset_from_vmcoreinfo(). This behavior will be problematic +in the later commits when we implement a trial-and-error approach +because the value of kaslr_offset could be passed to the outside of +calc_kaslr_offset() unexpectedly. Thus, fix this first. + +Signed-off-by: HATAYAMA Daisuke +--- + kaslr_helper.c | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git a/kaslr_helper.c b/kaslr_helper.c +index fe5909caa937..acbb5c2692e2 100644 +--- a/kaslr_helper.c ++++ b/kaslr_helper.c +@@ -394,10 +394,11 @@ quit: + #define PTI_USER_PGTABLE_MASK (1 << PTI_USER_PGTABLE_BIT) + #define CR3_PCID_MASK 0xFFFull + int +-calc_kaslr_offset(ulong *kaslr_offset, ulong *phys_base) ++calc_kaslr_offset(ulong *ko, ulong *pb) + { + uint64_t cr3 = 0, idtr = 0, pgd = 0, idtr_paddr; + ulong divide_error_vmcore; ++ ulong kaslr_offset, phys_base; + ulong kaslr_offset_kdump, phys_base_kdump; + int ret = FALSE; + int verbose = CRASHDEBUG(1)? 1: 0; +@@ -445,9 +446,9 @@ calc_kaslr_offset(ulong *kaslr_offset, ulong *phys_base) + + /* Now we can calculate kaslr_offset and phys_base */ + divide_error_vmcore = get_vec0_addr(idtr_paddr); +- *kaslr_offset = divide_error_vmcore - st->divide_error_vmlinux; +- *phys_base = idtr_paddr - +- (st->idt_table_vmlinux + *kaslr_offset - __START_KERNEL_map); ++ kaslr_offset = divide_error_vmcore - st->divide_error_vmlinux; ++ phys_base = idtr_paddr - ++ (st->idt_table_vmlinux + kaslr_offset - __START_KERNEL_map); + + if (CRASHDEBUG(1)) { + fprintf(fp, "calc_kaslr_offset: idtr=%lx\n", idtr); +@@ -465,9 +466,9 @@ calc_kaslr_offset(ulong *kaslr_offset, ulong *phys_base) + * from vmcoreinfo + */ + if (get_kaslr_offset_from_vmcoreinfo( +- *kaslr_offset, &kaslr_offset_kdump, &phys_base_kdump)) { +- *kaslr_offset = kaslr_offset_kdump; +- *phys_base = phys_base_kdump; ++ kaslr_offset, &kaslr_offset_kdump, &phys_base_kdump)) { ++ kaslr_offset = kaslr_offset_kdump; ++ phys_base = phys_base_kdump; + } else if (CRASHDEBUG(1)) { + fprintf(fp, "kaslr_helper: failed to determine which kernel was running at crash,\n"); + fprintf(fp, "kaslr_helper: asssuming the kdump 1st kernel.\n"); +@@ -475,10 +476,13 @@ calc_kaslr_offset(ulong *kaslr_offset, ulong *phys_base) + + if (CRASHDEBUG(1)) { + fprintf(fp, "calc_kaslr_offset: kaslr_offset=%lx\n", +- *kaslr_offset); +- fprintf(fp, "calc_kaslr_offset: phys_base=%lx\n", *phys_base); ++ kaslr_offset); ++ fprintf(fp, "calc_kaslr_offset: phys_base=%lx\n", phys_base); + } + ++ *ko = kaslr_offset; ++ *pb = phys_base; ++ + ret = TRUE; + quit: + vt->kernel_pgd[0] = 0; +-- +2.7.4 + + +From 8b50d94ada21f403665a5e562f40191f111e0313 Mon Sep 17 00:00:00 2001 +From: HATAYAMA Daisuke +Date: Mon, 27 Jul 2020 19:00:23 +0900 +Subject: [PATCH 4/4] kaslr: fix failure of calculating kaslr_offset due to an + sadump format restriction + +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. + + [ lijiang: adjust the code indent. ] + +Signed-off-by: HATAYAMA Daisuke +--- + kaslr_helper.c | 39 +++++++++++++++++++++++++++++++++++---- + sadump.c | 52 ++++++++++++++++++++++++++++------------------------ + 2 files changed, 63 insertions(+), 28 deletions(-) + +diff --git a/kaslr_helper.c b/kaslr_helper.c +index acbb5c2692e2..bb19e548d04e 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 35f7cf0fcf8f..009e17a4a44a 100644 +--- a/sadump.c ++++ b/sadump.c +@@ -1664,29 +1664,32 @@ get_sadump_data(void) + 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 offset; ++ struct sadump_header *sh = sd->dump_header; ++ static int apicid; ++ struct sadump_smram_cpu_state scs; ++ ++ if (apicid >= sh->nr_cpus) ++ return FALSE; ++ ++ offset = sd->sub_hdr_offset + sizeof(uint32_t) + ++ sd->dump_header->nr_cpus * sizeof(struct sadump_apic_state) + ++ apicid * sizeof(scs); ++ ++ 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 (scs.Cr3 && (scs.IdtUpper || scs.IdtLower)) { ++ *smram = scs; ++ return TRUE; ++ } ++ } ++ ++ return FALSE; + } + + int +@@ -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; +-- +2.7.4 + diff --git a/SPECS/crash.spec b/SPECS/crash.spec index d2138c1..e20f26b 100644 --- a/SPECS/crash.spec +++ b/SPECS/crash.spec @@ -4,7 +4,7 @@ Summary: Kernel analysis utility for live systems, netdump, diskdump, kdump, LKCD or mcore dumpfiles Name: crash Version: 7.2.8 -Release: 6%{?dist} +Release: 7%{?dist} License: GPLv3 Group: Development/Debuggers Source0: https://github.com/crash-utility/crash/archive/crash-%{version}.tar.gz @@ -22,6 +22,7 @@ Patch2: github_b80b16549e24.patch Patch3: github_0f29a8ac6b73.patch Patch4: github_1c45cea02df7.patch Patch5: github_9596b4388ea5.patch +Patch6: github_b97e7fd4e826_to_8b50d94ada21.patch %description The core analysis suite is a self-contained tool that can be used to @@ -48,6 +49,7 @@ offered by Mission Critical Linux, or the LKCD kernel patch. %patch3 -p1 -b github_0f29a8ac6b73.patch %patch4 -p1 -b github_1c45cea02df7.patch %patch5 -p1 -b github_9596b4388ea5.patch +%patch6 -p1 -b github_b97e7fd4e826_to_8b50d94ada21.patch %build cp %{SOURCE1} . @@ -78,6 +80,10 @@ rm -rf %{buildroot} %{_includedir}/* %changelog +* Mon Aug 17 2020 Bhupesh Sharma - 7.2.8-7 +- crash/sadump, kaslr: fix failure of calculating kaslr_offset due to an sadump format restriction + Resolves: rhbz#1855527 + * Fri Aug 7 2020 Bhupesh Sharma - 7.2.8-6 - aarch64: Revert to reading CONFIG_ARM64_USER_VA_BITS_52 and CONFIG_ARM64_PA_BITS=52 for 52-bit VA/PA space. Resolves: rhbz#1861086