Message ID | fe78d723ba64456d68754a944fa93fe4a25c730f.1605046192.git.andreyknvl@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | kasan: add hardware tag-based mode for arm64 | expand |
On Tue, Nov 10, 2020 at 11:12 PM 'Andrey Konovalov' via kasan-dev <kasan-dev@googlegroups.com> wrote: > > Add error reporting for hardware tag-based KASAN. When CONFIG_KASAN_HW_TAGS > is enabled, print KASAN report from the arm64 tag fault handler. > > SAS bits aren't set in ESR for all faults reported in EL1, so it's > impossible to find out the size of the access the caused the fault. > Adapt KASAN reporting code to handle this case. > > Signed-off-by: Andrey Konovalov <andreyknvl@google.com> > Co-developed-by: Vincenzo Frascino <vincenzo.frascino@arm.com> > Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com> > Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> Reviewed-by: Alexander Potapenko <glider@google.com> > --- > Change-Id: I3780fe7db6e075dff2937d3d8508f55c9322b095 > --- > arch/arm64/mm/fault.c | 14 ++++++++++++++ > mm/kasan/report.c | 11 ++++++++--- > 2 files changed, 22 insertions(+), 3 deletions(-) > > diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c > index fbceb14d93b1..7370e822e588 100644 > --- a/arch/arm64/mm/fault.c > +++ b/arch/arm64/mm/fault.c > @@ -14,6 +14,7 @@ > #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> > @@ -297,10 +298,23 @@ static void die_kernel_fault(const char *msg, unsigned long addr, > 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) > diff --git a/mm/kasan/report.c b/mm/kasan/report.c > index 8afc1a6ab202..ce06005d4052 100644 > --- a/mm/kasan/report.c > +++ b/mm/kasan/report.c > @@ -62,9 +62,14 @@ static void print_error_description(struct kasan_access_info *info) > { > 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); > -- > 2.29.2.222.g5d2a92d10f8-goog > > -- > You received this message because you are subscribed to the Google Groups "kasan-dev" group. > To unsubscribe from this group and stop receiving emails from it, send an email to kasan-dev+unsubscribe@googlegroups.com. > To view this discussion on the web visit https://groups.google.com/d/msgid/kasan-dev/fe78d723ba64456d68754a944fa93fe4a25c730f.1605046192.git.andreyknvl%40google.com.
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index fbceb14d93b1..7370e822e588 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -14,6 +14,7 @@ #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> @@ -297,10 +298,23 @@ static void die_kernel_fault(const char *msg, unsigned long addr, 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) diff --git a/mm/kasan/report.c b/mm/kasan/report.c index 8afc1a6ab202..ce06005d4052 100644 --- a/mm/kasan/report.c +++ b/mm/kasan/report.c @@ -62,9 +62,14 @@ static void print_error_description(struct kasan_access_info *info) { 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);