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

kasan: disable LOCKDEP when printing reports

If LOCKDEP detects a bug while KASAN is printing a report and if
panic_on_warn is set, KASAN will not be able to finish.  Disable LOCKDEP
while KASAN is printing a report.

See https://bugzilla.kernel.org/show_bug.cgi?id=202115 for an example
of the issue.

Link: https://lkml.kernel.org/r/c48a2a3288200b07e1788b77365c2f02784cfeb4.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 80207910
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/ftrace.h> #include <linux/ftrace.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/lockdep.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -148,6 +149,8 @@ static void start_report(unsigned long *flags, bool sync) ...@@ -148,6 +149,8 @@ static void start_report(unsigned long *flags, bool sync)
disable_trace_on_warning(); disable_trace_on_warning();
/* Update status of the currently running KASAN test. */ /* Update status of the currently running KASAN test. */
update_kunit_status(sync); update_kunit_status(sync);
/* Do not allow LOCKDEP mangling KASAN reports. */
lockdep_off();
/* Make sure we don't end up in loop. */ /* Make sure we don't end up in loop. */
kasan_disable_current(); kasan_disable_current();
spin_lock_irqsave(&report_lock, *flags); spin_lock_irqsave(&report_lock, *flags);
...@@ -160,12 +163,13 @@ static void end_report(unsigned long *flags, void *addr) ...@@ -160,12 +163,13 @@ static void end_report(unsigned long *flags, void *addr)
trace_error_report_end(ERROR_DETECTOR_KASAN, trace_error_report_end(ERROR_DETECTOR_KASAN,
(unsigned long)addr); (unsigned long)addr);
pr_err("==================================================================\n"); pr_err("==================================================================\n");
add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
spin_unlock_irqrestore(&report_lock, *flags); spin_unlock_irqrestore(&report_lock, *flags);
if (panic_on_warn && !test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags)) if (panic_on_warn && !test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags))
panic("panic_on_warn set ...\n"); panic("panic_on_warn set ...\n");
if (kasan_arg_fault == KASAN_ARG_FAULT_PANIC) if (kasan_arg_fault == KASAN_ARG_FAULT_PANIC)
panic("kasan.fault=panic set ...\n"); panic("kasan.fault=panic set ...\n");
add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
lockdep_on();
kasan_enable_current(); kasan_enable_current();
} }
......
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