diff --git a/mm/kasan/report.c b/mm/kasan/report.c index 8357e1a33699..7edde1a26a41 100644 --- a/mm/kasan/report.c +++ b/mm/kasan/report.c @@ -681,11 +681,56 @@ void kasan_non_canonical_hook(unsigned long addr) const char *bug_type; /* - * All addresses that came as a result of the memory-to-shadow mapping - * (even for bogus pointers) must be >= KASAN_SHADOW_OFFSET. + * For Generic KASAN, kasan_mem_to_shadow() uses the logical right shift + * and never overflows with the chosen KASAN_SHADOW_OFFSET values (on + * both x86 and arm64). Thus, the possible shadow addresses (even for + * bogus pointers) belong to a single contiguous region that is the + * result of kasan_mem_to_shadow() applied to the whole address space. */ - if (addr < KASAN_SHADOW_OFFSET) - return; + if (IS_ENABLED(CONFIG_KASAN_GENERIC)) { + if (addr < (u64)kasan_mem_to_shadow((void *)(0UL)) || + addr > (u64)kasan_mem_to_shadow((void *)(~0UL))) + return; + } + + /* + * For Software Tag-Based KASAN, kasan_mem_to_shadow() uses the + * arithmetic shift. Normally, this would make checking for a possible + * shadow address complicated, as the shadow address computation + * operation would overflow only for some memory addresses. However, due + * to the chosen KASAN_SHADOW_OFFSET values and the fact the + * kasan_mem_to_shadow() only operates on pointers with the tag reset, + * the overflow always happens (for both x86 and arm64). + * + * For arm64, the top byte of the pointer gets reset to 0xFF. Thus, the + * possible shadow addresses belong to a region that is the result of + * kasan_mem_to_shadow() applied to the memory range + * [0xFF000000000000, 0xFFFFFFFFFFFFFFFF]. Despite the overflow, the + * resulting possible shadow region is contiguous, as the overflow + * happens for both 0xFF000000000000 and 0xFFFFFFFFFFFFFFFF. + */ + if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) && IS_ENABLED(CONFIG_ARM64)) { + if (addr < (u64)kasan_mem_to_shadow((void *)(0xFFUL << 56)) || + addr > (u64)kasan_mem_to_shadow((void *)(~0UL))) + return; + } + + /* + * For x86-64, only the pointer bits [62:57] get reset, and bits #63 + * and #56 can be 0 or 1. Thus, kasan_mem_to_shadow() can be possibly + * applied to two regions of memory: + * [0x7E00000000000000, 0x7FFFFFFFFFFFFFFF] and + * [0xFE00000000000000, 0xFFFFFFFFFFFFFFFF]. As the overflow happens + * for both ends of both memory ranges, both possible shadow regions + * are contiguous. + */ + if (IS_ENABLED(CONFIG_KASAN_SW_TAGS) && IS_ENABLED(CONFIG_X86_64)) { + if ((addr < (u64)kasan_mem_to_shadow((void *)(0x7EUL << 56)) || + addr > (u64)kasan_mem_to_shadow((void *)(~0UL >> 1))) && + (addr < (u64)kasan_mem_to_shadow((void *)(0xFEUL << 56)) || + addr > (u64)kasan_mem_to_shadow((void *)(~0UL)))) + return; + } orig_addr = (unsigned long)kasan_shadow_to_mem((void *)addr);