Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bug: fix "cut here" location for __WARN_TAINT architectures

Prior to v4.11, x86 used warn_slowpath_fmt() for handling WARN()s.
After WARN() was moved to using UD0 on x86, the warning text started
appearing _before_ the "cut here" line. This appears to have been a
long-standing bug on architectures that used __WARN_TAINT, but it didn't
get fixed.

v4.11 and earlier on x86:

------------[ cut here ]------------
WARNING: CPU: 0 PID: 2956 at drivers/misc/lkdtm_bugs.c:65 lkdtm_WARNING+0x21/0x30
This is a warning message
Modules linked in:

v4.12 and later on x86:

This is a warning message
------------[ cut here ]------------
WARNING: CPU: 1 PID: 2982 at drivers/misc/lkdtm_bugs.c:68 lkdtm_WARNING+0x15/0x20
Modules linked in:

With this fix:

------------[ cut here ]------------
This is a warning message
WARNING: CPU: 3 PID: 3009 at drivers/misc/lkdtm_bugs.c:67 lkdtm_WARNING+0x15/0x20

Since the __FILE__ reporting happens as part of the UD0 handler, it
isn't trivial to move the message to after the WARNING line, but at
least we can fix the position of the "cut here" line so all the various
logging tools will start including the actual runtime warning message
again, when they follow the instruction and "cut here".

Link: http://lkml.kernel.org/r/1510100869-73751-4-git-send-email-keescook@chromium.org
Fixes: 9a93848fe787 ("x86/debug: Implement __WARN() using UD0")
Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Kees Cook and committed by
Linus Torvalds
a7bed27a 2a8358d8

+18 -3
+3 -2
include/asm-generic/bug.h
··· 92 92 #define __WARN_printf_taint(taint, arg...) \ 93 93 warn_slowpath_fmt_taint(__FILE__, __LINE__, taint, arg) 94 94 #else 95 + extern __printf(1, 2) void __warn_printk(const char *fmt, ...); 95 96 #define __WARN() __WARN_TAINT(TAINT_WARN) 96 - #define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0) 97 + #define __WARN_printf(arg...) do { __warn_printk(arg); __WARN(); } while (0) 97 98 #define __WARN_printf_taint(taint, arg...) \ 98 - do { printk(arg); __WARN_TAINT(taint); } while (0) 99 + do { __warn_printk(arg); __WARN_TAINT(taint); } while (0) 99 100 #endif 100 101 101 102 /* used internally by panic.c */
+15 -1
kernel/panic.c
··· 520 520 { 521 521 disable_trace_on_warning(); 522 522 523 - pr_warn(CUT_HERE); 523 + if (args) 524 + pr_warn(CUT_HERE); 524 525 525 526 if (file) 526 527 pr_warn("WARNING: CPU: %d PID: %d at %s:%d %pS\n", ··· 585 584 586 585 void warn_slowpath_null(const char *file, int line) 587 586 { 587 + pr_warn(CUT_HERE); 588 588 __warn(file, line, __builtin_return_address(0), TAINT_WARN, NULL, NULL); 589 589 } 590 590 EXPORT_SYMBOL(warn_slowpath_null); 591 + #else 592 + void __warn_printk(const char *fmt, ...) 593 + { 594 + va_list args; 595 + 596 + pr_warn(CUT_HERE); 597 + 598 + va_start(args, fmt); 599 + vprintk(fmt, args); 600 + va_end(args); 601 + } 602 + EXPORT_SYMBOL(__warn_printk); 591 603 #endif 592 604 593 605 #ifdef CONFIG_BUG