| From 1b4cfe3c0a30dde968fb43c577a8d7e262a145ee Mon Sep 17 00:00:00 2001 |
| From: Kees Cook <keescook@chromium.org> |
| Date: Fri, 9 Mar 2018 15:51:02 -0800 |
| Subject: lib/bug.c: exclude non-BUG/WARN exceptions from report_bug() |
| |
| From: Kees Cook <keescook@chromium.org> |
| |
| commit 1b4cfe3c0a30dde968fb43c577a8d7e262a145ee upstream. |
| |
| Commit b8347c219649 ("x86/debug: Handle warnings before the notifier |
| chain, to fix KGDB crash") changed the ordering of fixups, and did not |
| take into account the case of x86 processing non-WARN() and non-BUG() |
| exceptions. This would lead to output of a false BUG line with no other |
| information. |
| |
| In the case of a refcount exception, it would be immediately followed by |
| the refcount WARN(), producing very strange double-"cut here": |
| |
| lkdtm: attempting bad refcount_inc() overflow |
| ------------[ cut here ]------------ |
| Kernel BUG at 0000000065f29de5 [verbose debug info unavailable] |
| ------------[ cut here ]------------ |
| refcount_t overflow at lkdtm_REFCOUNT_INC_OVERFLOW+0x6b/0x90 in cat[3065], uid/euid: 0/0 |
| WARNING: CPU: 0 PID: 3065 at kernel/panic.c:657 refcount_error_report+0x9a/0xa4 |
| ... |
| |
| In the prior ordering, exceptions were searched first: |
| |
| do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str, |
| ... |
| if (fixup_exception(regs, trapnr)) |
| return 0; |
| |
| - if (fixup_bug(regs, trapnr)) |
| - return 0; |
| - |
| |
| As a result, fixup_bugs()'s is_valid_bugaddr() didn't take into account |
| needing to search the exception list first, since that had already |
| happened. |
| |
| So, instead of searching the exception list twice (once in |
| is_valid_bugaddr() and then again in fixup_exception()), just add a |
| simple sanity check to report_bug() that will immediately bail out if a |
| BUG() (or WARN()) entry is not found. |
| |
| Link: http://lkml.kernel.org/r/20180301225934.GA34350@beast |
| Fixes: b8347c219649 ("x86/debug: Handle warnings before the notifier chain, to fix KGDB crash") |
| Signed-off-by: Kees Cook <keescook@chromium.org> |
| Cc: Ingo Molnar <mingo@kernel.org> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Borislav Petkov <bp@alien8.de> |
| Cc: Richard Weinberger <richard.weinberger@gmail.com> |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| lib/bug.c | 2 ++ |
| 1 file changed, 2 insertions(+) |
| |
| --- a/lib/bug.c |
| +++ b/lib/bug.c |
| @@ -150,6 +150,8 @@ enum bug_trap_type report_bug(unsigned l |
| return BUG_TRAP_TYPE_NONE; |
| |
| bug = find_bug(bugaddr); |
| + if (!bug) |
| + return BUG_TRAP_TYPE_NONE; |
| |
| file = NULL; |
| line = 0; |