flush_cache_vmap() sets a per-CPU flag, and a kernel page fault that finds the flag set gets an sfence.vma and a retry. flush_cache_vmap() only sets the flag for vmalloc, module and vmemmap ranges. kasan_populate_vmalloc() maps new shadow pages and calls flush_cache_vmap() on the shadow range, so no flag gets set. For vmap()-style areas, kasan_unpoison_vmalloc() writes the new shadow right away. If the CPU hasn’t seen the new entry yet, the store faults, and since there is no flag set, the kernel crashes. [ 0.675216] Unable to handle kernel paging request at virtual address fffffff7c009a000 Current swapper/0 pgtable: 4K pagesize, 39-bit VAs, pgdp=0x0000000004504000 [fffffff7c009a000] pgd=000000009ff6e001, p4d=000000009ff6e001, pud=000000009ff6e001, pmd=00000000400e7401, pte=00000000403cb0e7 status: 0000000200000120 badaddr: fffffff7c009a000 cause: 000000000000000f __memset+0x60/0xfe kasan_unpoison+0x26/0x4e __kasan_unpoison_vmalloc+0x20/0x2e __get_vm_area_node+0x1c6/0x276 get_vm_area_caller+0x52/0x84 vmap+0xf0/0x264 dma_common_contiguous_remap+0xa0/0xd0 atomic_pool_expand+0xb6/0x310 __dma_atomic_pool_init.isra.0+0xf6/0x1c0 dma_atomic_pool_init+0xf6/0x1aa do_one_initcall+0x134/0x928 kernel_init_freeable+0x532/0x60a kernel_init+0x28/0x162 ret_from_fork_kernel+0x82/0x94c ret_from_fork_kernel_asm+0x16/0x18 The PTE is valid, so the mapping was in place when the CPU faulted. Tested on Orange Pi RV2: without this patch 2 of 30 boots crashed, with it 50 of 50 booted. Add the KASAN shadow region to the ranges for which flush_cache_vmap() calls mark_new_valid_map(), as commit 4edd70ee6a7d ("mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap") did for vmemmap. Fixes: 503638e0babf ("riscv: Stop emitting preventive sfence.vma for new vmalloc mappings") Signed-off-by: Ali Tariq --- Crash Log: https://kernelci.cloud-v.co/scheduler/job/541 --- arch/riscv/include/asm/cacheflush.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h index c2b0a2928f06..c95b2f6007fd 100644 --- a/arch/riscv/include/asm/cacheflush.h +++ b/arch/riscv/include/asm/cacheflush.h @@ -8,6 +8,8 @@ #include +#include + static inline void local_flush_icache_all(void) { asm volatile ("fence.i" ::: "memory"); @@ -57,7 +59,9 @@ static inline void mark_new_valid_map(void) static inline void flush_cache_vmap(unsigned long start, unsigned long end) { if (is_vmalloc_or_module_addr((void *)start) || - (start >= VMEMMAP_START && end <= VMEMMAP_END)) + (start >= VMEMMAP_START && end <= VMEMMAP_END) || + (IS_ENABLED(CONFIG_KASAN) && + start >= KASAN_SHADOW_START && end <= KASAN_SHADOW_END)) mark_new_valid_map(); } #define flush_cache_vmap_early(start, end) local_flush_tlb_kernel_range(start, end) -- 2.34.1