commit 6d0d95ecc04a70f8448d562ff0fbbae237f5c929 Author: Kazuhito Hagio Date: Thu Apr 21 08:58:29 2022 +0900 [PATCH] Avoid false-positive mem_section validation with vmlinux Currently get_mem_section() validates if SYMBOL(mem_section) is the address of the mem_section array first. But there was a report that the first validation wrongly returned TRUE with -x vmlinux and SPARSEMEM_EXTREME (4.15+) on s390x. This leads to crash failing statup with the following seek error: crash: seek error: kernel virtual address: 67fffc2800 type: "memory section root table" Skip the first validation when satisfying the conditions. Reported-by: Dave Wysochanski Signed-off-by: Kazuhito Hagio Reviewed-and-Tested-by: Philipp Rudo Reviewed-by: Pingfan Liu diff --git a/makedumpfile-1.7.0/makedumpfile.c b/makedumpfile-1.7.0/makedumpfile.c index a2f45c84cee3ba57ce3d3cf3f1905e6a03f4fd09..65d1c7c2f02c9ae8ead9de0f0217235fe72b3ca7 100644 --- a/makedumpfile-1.7.0/makedumpfile.c +++ b/makedumpfile-1.7.0/makedumpfile.c @@ -3698,6 +3698,22 @@ validate_mem_section(unsigned long *mem_sec, return ret; } +/* + * SYMBOL(mem_section) varies with the combination of memory model and + * its source: + * + * SPARSEMEM + * vmcoreinfo: address of mem_section root array + * -x vmlinux: address of mem_section root array + * + * SPARSEMEM_EXTREME v1 + * vmcoreinfo: address of mem_section root array + * -x vmlinux: address of mem_section root array + * + * SPARSEMEM_EXTREME v2 (with 83e3c48729d9 and a0b1280368d1) 4.15+ + * vmcoreinfo: address of mem_section root array + * -x vmlinux: address of pointer to mem_section root array + */ static int get_mem_section(unsigned int mem_section_size, unsigned long *mem_maps, unsigned int num_section) @@ -3710,12 +3726,27 @@ get_mem_section(unsigned int mem_section_size, unsigned long *mem_maps, strerror(errno)); return FALSE; } + + /* + * There was a report that the first validation wrongly returned TRUE + * with -x vmlinux and SPARSEMEM_EXTREME v2 on s390x, so skip it. + * Howerver, leave the fallback validation as it is for the -i option. + */ + if (is_sparsemem_extreme() && info->name_vmlinux) { + unsigned long flag = 0; + if (get_symbol_type_name("mem_section", DWARF_INFO_GET_SYMBOL_TYPE, + NULL, &flag) + && !(flag & TYPE_ARRAY)) + goto skip_1st_validation; + } + ret = validate_mem_section(mem_sec, SYMBOL(mem_section), mem_section_size, mem_maps, num_section); if (!ret && is_sparsemem_extreme()) { unsigned long mem_section_ptr; +skip_1st_validation: if (!readmem(VADDR, SYMBOL(mem_section), &mem_section_ptr, sizeof(mem_section_ptr))) goto out;