Commit c068664c authored by Andrey Konovalov's avatar Andrey Konovalov Committed by Linus Torvalds

kasan: respect KASAN_BIT_REPORTED in all reporting routines

Currently, only kasan_report() checks the KASAN_BIT_REPORTED and
KASAN_BIT_MULTI_SHOT flags.

Make other reporting routines check these flags as well.

Also add explanatory comments.

Note that the current->kasan_depth check is split out into
report_suppressed() and only called for kasan_report().

Link: https://lkml.kernel.org/r/715e346b10b398e29ba1b425299dcd79e29d58ce.1646237226.git.andreyknvl@google.comSigned-off-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Marco Elver <elver@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 795b760f
...@@ -381,12 +381,26 @@ static void print_memory_metadata(const void *addr) ...@@ -381,12 +381,26 @@ static void print_memory_metadata(const void *addr)
} }
} }
static bool report_enabled(void) /*
* Used to suppress reports within kasan_disable/enable_current() critical
* sections, which are used for marking accesses to slab metadata.
*/
static bool report_suppressed(void)
{ {
#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
if (current->kasan_depth) if (current->kasan_depth)
return false; return true;
#endif #endif
return false;
}
/*
* Used to avoid reporting more than one KASAN bug unless kasan_multi_shot
* is enabled. Note that KASAN tests effectively enable kasan_multi_shot
* for their duration.
*/
static bool report_enabled(void)
{
if (test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags)) if (test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags))
return true; return true;
return !test_and_set_bit(KASAN_BIT_REPORTED, &kasan_flags); return !test_and_set_bit(KASAN_BIT_REPORTED, &kasan_flags);
...@@ -416,6 +430,14 @@ void kasan_report_invalid_free(void *ptr, unsigned long ip) ...@@ -416,6 +430,14 @@ void kasan_report_invalid_free(void *ptr, unsigned long ip)
unsigned long flags; unsigned long flags;
struct kasan_report_info info; struct kasan_report_info info;
/*
* Do not check report_suppressed(), as an invalid-free cannot be
* caused by accessing slab metadata and thus should not be
* suppressed by kasan_disable/enable_current() critical sections.
*/
if (unlikely(!report_enabled()))
return;
start_report(&flags, true); start_report(&flags, true);
info.type = KASAN_REPORT_INVALID_FREE; info.type = KASAN_REPORT_INVALID_FREE;
...@@ -444,7 +466,7 @@ bool kasan_report(unsigned long addr, size_t size, bool is_write, ...@@ -444,7 +466,7 @@ bool kasan_report(unsigned long addr, size_t size, bool is_write,
unsigned long irq_flags; unsigned long irq_flags;
struct kasan_report_info info; struct kasan_report_info info;
if (unlikely(!report_enabled())) { if (unlikely(report_suppressed()) || unlikely(!report_enabled())) {
ret = false; ret = false;
goto out; goto out;
} }
...@@ -473,6 +495,13 @@ void kasan_report_async(void) ...@@ -473,6 +495,13 @@ void kasan_report_async(void)
{ {
unsigned long flags; unsigned long flags;
/*
* Do not check report_suppressed(), as kasan_disable/enable_current()
* critical sections do not affect Hardware Tag-Based KASAN.
*/
if (unlikely(!report_enabled()))
return;
start_report(&flags, false); start_report(&flags, false);
pr_err("BUG: KASAN: invalid-access\n"); pr_err("BUG: KASAN: invalid-access\n");
pr_err("Asynchronous fault: no details available\n"); pr_err("Asynchronous fault: no details available\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment