#include <linux/mm.h>
 #include <linux/hardirq.h>
 #include <linux/init.h>
+#include <linux/kasan.h>
 #include <linux/kprobes.h>
 #include <linux/uaccess.h>
 #include <linux/page-flags.h>
        do_exit(SIGKILL);
 }
 
+#ifdef CONFIG_KASAN_HW_TAGS
 static void report_tag_fault(unsigned long addr, unsigned int esr,
                             struct pt_regs *regs)
 {
+       bool is_write  = ((esr & ESR_ELx_WNR) >> ESR_ELx_WNR_SHIFT) != 0;
+
+       /*
+        * SAS bits aren't set for all faults reported in EL1, so we can't
+        * find out access size.
+        */
+       kasan_report(addr, 0, is_write, regs->pc);
 }
+#else
+/* Tag faults aren't enabled without CONFIG_KASAN_HW_TAGS. */
+static inline void report_tag_fault(unsigned long addr, unsigned int esr,
+                                   struct pt_regs *regs) { }
+#endif
 
 static void do_tag_recovery(unsigned long addr, unsigned int esr,
                           struct pt_regs *regs)
 
 {
        pr_err("BUG: KASAN: %s in %pS\n",
                get_bug_type(info), (void *)info->ip);
-       pr_err("%s of size %zu at addr %px by task %s/%d\n",
-               info->is_write ? "Write" : "Read", info->access_size,
-               info->access_addr, current->comm, task_pid_nr(current));
+       if (info->access_size)
+               pr_err("%s of size %zu at addr %px by task %s/%d\n",
+                       info->is_write ? "Write" : "Read", info->access_size,
+                       info->access_addr, current->comm, task_pid_nr(current));
+       else
+               pr_err("%s at addr %px by task %s/%d\n",
+                       info->is_write ? "Write" : "Read",
+                       info->access_addr, current->comm, task_pid_nr(current));
 }
 
 static DEFINE_SPINLOCK(report_lock);