]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
kasan: fix bug type classification for SW_TAGS mode
authorAndrey Ryabinin <ryabinin.a.a@gmail.com>
Thu, 5 Mar 2026 18:56:59 +0000 (19:56 +0100)
committerAndrew Morton <akpm@linux-foundation.org>
Sun, 5 Apr 2026 20:53:18 +0000 (13:53 -0700)
kasan_non_canonical_hook() derives orig_addr from kasan_shadow_to_mem(),
but the pointer tag may remain in the top byte.  In SW_TAGS mode this
tagged address is compared against PAGE_SIZE and TASK_SIZE, which leads to
incorrect bug classification.

As a result, NULL pointer dereferences may be reported as
"wild-memory-access".

Strip the tag before performing these range checks and use the untagged
value when reporting addresses in these ranges.

Before:
  [ ] Unable to handle kernel paging request at virtual address ffef800000000000
  [ ] KASAN: maybe wild-memory-access in range [0xff00000000000000-0xff0000000000000f]

After:
  [ ] Unable to handle kernel paging request at virtual address ffef800000000000
  [ ] KASAN: null-ptr-deref in range [0x0000000000000000-0x000000000000000f]

Link: https://lkml.kernel.org/r/20260305185659.20807-1-ryabinin.a.a@gmail.com
Signed-off-by: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Konovalov <andreyknvl@gmail.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/kasan/report.c

index 27efb78eb32d57e56df54b8747116d97e5e92d60..e804b1e1f88693f439de55df21eac82c2a78e7e3 100644 (file)
@@ -638,7 +638,7 @@ void kasan_report_async(void)
  */
 void kasan_non_canonical_hook(unsigned long addr)
 {
-       unsigned long orig_addr;
+       unsigned long orig_addr, user_orig_addr;
        const char *bug_type;
 
        /*
@@ -650,6 +650,9 @@ void kasan_non_canonical_hook(unsigned long addr)
 
        orig_addr = (unsigned long)kasan_shadow_to_mem((void *)addr);
 
+       /* Strip pointer tag before comparing against userspace ranges */
+       user_orig_addr = (unsigned long)set_tag((void *)orig_addr, 0);
+
        /*
         * For faults near the shadow address for NULL, we can be fairly certain
         * that this is a KASAN shadow memory access.
@@ -661,11 +664,13 @@ void kasan_non_canonical_hook(unsigned long addr)
         * address, but make it clear that this is not necessarily what's
         * actually going on.
         */
-       if (orig_addr < PAGE_SIZE)
+       if (user_orig_addr < PAGE_SIZE) {
                bug_type = "null-ptr-deref";
-       else if (orig_addr < TASK_SIZE)
+               orig_addr = user_orig_addr;
+       } else if (user_orig_addr < TASK_SIZE) {
                bug_type = "probably user-memory-access";
-       else if (addr_in_shadow((void *)addr))
+               orig_addr = user_orig_addr;
+       } else if (addr_in_shadow((void *)addr))
                bug_type = "probably wild-memory-access";
        else
                bug_type = "maybe wild-memory-access";