From c604b40728c28ba4d831832c7f03805aba11a8e2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:03 +0200 Subject: [PATCH 01/16] lib/test_printf: Mark big constant with UL Sparse complains that constant is so big for unsigned long on 64-bit architecture. lib/test_printf.c:217:54: warning: constant 0xffff0123456789ab is so big it is unsigned long lib/test_printf.c:246:54: warning: constant 0xffff0123456789ab is so big it is unsigned long To satisfy everyone, mark the constant with UL. Link: http://lkml.kernel.org/r/20180216210711.79901-1-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko [pmladek@suse.com: Changed from ULL to UL as suggested by Luc Van Oostenryck ] Signed-off-by: Petr Mladek --- lib/test_printf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/test_printf.c b/lib/test_printf.c index 71ebfa43ad05..cea592f402ed 100644 --- a/lib/test_printf.c +++ b/lib/test_printf.c @@ -204,7 +204,7 @@ test_string(void) #if BITS_PER_LONG == 64 #define PTR_WIDTH 16 -#define PTR ((void *)0xffff0123456789ab) +#define PTR ((void *)0xffff0123456789abUL) #define PTR_STR "ffff0123456789ab" #define ZEROS "00000000" /* hex 32 zero bits */ From ce0b4910bdf8c515fe8be49a6c582ee8b206ca0a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:04 +0200 Subject: [PATCH 02/16] lib/vsprintf: Make dec_spec global There are places where default specification to print decimal numbers is in use. Make it global and convert existing users. Link: http://lkml.kernel.org/r/20180216210711.79901-2-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index d7a708f82559..8f29af063d8a 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -693,6 +693,11 @@ char *symbol_string(char *buf, char *end, void *ptr, #endif } +static const struct printf_spec default_dec_spec = { + .base = 10, + .precision = -1, +}; + static noinline_for_stack char *resource_string(char *buf, char *end, struct resource *res, struct printf_spec spec, const char *fmt) @@ -722,11 +727,6 @@ char *resource_string(char *buf, char *end, struct resource *res, .precision = -1, .flags = SMALL | ZEROPAD, }; - static const struct printf_spec dec_spec = { - .base = 10, - .precision = -1, - .flags = 0, - }; static const struct printf_spec str_spec = { .field_width = -1, .precision = 10, @@ -760,10 +760,10 @@ char *resource_string(char *buf, char *end, struct resource *res, specp = &mem_spec; } else if (res->flags & IORESOURCE_IRQ) { p = string(p, pend, "irq ", str_spec); - specp = &dec_spec; + specp = &default_dec_spec; } else if (res->flags & IORESOURCE_DMA) { p = string(p, pend, "dma ", str_spec); - specp = &dec_spec; + specp = &default_dec_spec; } else if (res->flags & IORESOURCE_BUS) { p = string(p, pend, "bus ", str_spec); specp = &bus_spec; @@ -903,9 +903,6 @@ char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap, int cur, rbot, rtop; bool first = true; - /* reused to print numbers */ - spec = (struct printf_spec){ .base = 10 }; - rbot = cur = find_first_bit(bitmap, nr_bits); while (cur < nr_bits) { rtop = cur; @@ -920,13 +917,13 @@ char *bitmap_list_string(char *buf, char *end, unsigned long *bitmap, } first = false; - buf = number(buf, end, rbot, spec); + buf = number(buf, end, rbot, default_dec_spec); if (rbot < rtop) { if (buf < end) *buf = '-'; buf++; - buf = number(buf, end, rtop, spec); + buf = number(buf, end, rtop, default_dec_spec); } rbot = cur; From abd4fe6276fa1111453f96cefa7145b6d15868ca Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:05 +0200 Subject: [PATCH 03/16] lib/vsprintf: Make strspec global There are places where default specification to print strings is in use. Make it global and convert existing users. Link: http://lkml.kernel.org/r/20180216210711.79901-3-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 8f29af063d8a..0c23b006b495 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -693,6 +693,11 @@ char *symbol_string(char *buf, char *end, void *ptr, #endif } +static const struct printf_spec default_str_spec = { + .field_width = -1, + .precision = -1, +}; + static const struct printf_spec default_dec_spec = { .base = 10, .precision = -1, @@ -1461,10 +1466,6 @@ char *format_flags(char *buf, char *end, unsigned long flags, const struct trace_print_flags *names) { unsigned long mask; - const struct printf_spec strspec = { - .field_width = -1, - .precision = -1, - }; const struct printf_spec numspec = { .flags = SPECIAL|SMALL, .field_width = -1, @@ -1477,7 +1478,7 @@ char *format_flags(char *buf, char *end, unsigned long flags, if ((flags & mask) != mask) continue; - buf = string(buf, end, names->name, strspec); + buf = string(buf, end, names->name, default_str_spec); flags &= ~mask; if (flags) { @@ -1535,22 +1536,18 @@ char *device_node_gen_full_name(const struct device_node *np, char *buf, char *e { int depth; const struct device_node *parent = np->parent; - static const struct printf_spec strspec = { - .field_width = -1, - .precision = -1, - }; /* special case for root node */ if (!parent) - return string(buf, end, "/", strspec); + return string(buf, end, "/", default_str_spec); for (depth = 0; parent->parent; depth++) parent = parent->parent; for ( ; depth >= 0; depth--) { - buf = string(buf, end, "/", strspec); + buf = string(buf, end, "/", default_str_spec); buf = string(buf, end, device_node_name_for_depth(np, depth), - strspec); + default_str_spec); } return buf; } From 544339730844674058e772084948cfcc9e62a3c5 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:06 +0200 Subject: [PATCH 04/16] lib/vsprintf: Make flag_spec global There are places where default specification to print flags as number is in use. Make it global and convert existing users. Link: http://lkml.kernel.org/r/20180216210711.79901-4-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 0c23b006b495..c789d265311b 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -698,6 +698,12 @@ static const struct printf_spec default_str_spec = { .precision = -1, }; +static const struct printf_spec default_flag_spec = { + .base = 16, + .precision = -1, + .flags = SPECIAL | SMALL, +}; + static const struct printf_spec default_dec_spec = { .base = 10, .precision = -1, @@ -737,11 +743,6 @@ char *resource_string(char *buf, char *end, struct resource *res, .precision = 10, .flags = LEFT, }; - static const struct printf_spec flag_spec = { - .base = 16, - .precision = -1, - .flags = SPECIAL | SMALL, - }; /* 32-bit res (sizeof==4): 10 chars in dec, 10 in hex ("0x" + 8) * 64-bit res (sizeof==8): 20 chars in dec, 18 in hex ("0x" + 16) */ @@ -798,7 +799,7 @@ char *resource_string(char *buf, char *end, struct resource *res, p = string(p, pend, " disabled", str_spec); } else { p = string(p, pend, " flags ", str_spec); - p = number(p, pend, res->flags, flag_spec); + p = number(p, pend, res->flags, default_flag_spec); } *p++ = ']'; *p = '\0'; @@ -1466,12 +1467,6 @@ char *format_flags(char *buf, char *end, unsigned long flags, const struct trace_print_flags *names) { unsigned long mask; - const struct printf_spec numspec = { - .flags = SPECIAL|SMALL, - .field_width = -1, - .precision = -1, - .base = 16, - }; for ( ; flags && names->name; names++) { mask = names->mask; @@ -1489,7 +1484,7 @@ char *format_flags(char *buf, char *end, unsigned long flags, } if (flags) - buf = number(buf, end, flags, numspec); + buf = number(buf, end, flags, default_flag_spec); return buf; } From 558594f3c2a5cd65f18b976faf68143c502b73b2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:07 +0200 Subject: [PATCH 05/16] lib/vsprintf: Move pointer_string() upper As preparatory patch to further clean up. No functional change. Link: http://lkml.kernel.org/r/20180216210711.79901-5-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index c789d265311b..87dbced51b1a 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1347,6 +1347,20 @@ char *uuid_string(char *buf, char *end, const u8 *addr, return string(buf, end, uuid, spec); } +static noinline_for_stack +char *pointer_string(char *buf, char *end, const void *ptr, + struct printf_spec spec) +{ + spec.base = 16; + spec.flags |= SMALL; + if (spec.field_width == -1) { + spec.field_width = 2 * sizeof(ptr); + spec.flags |= ZEROPAD; + } + + return number(buf, end, (unsigned long int)ptr, spec); +} + int kptr_restrict __read_mostly; static noinline_for_stack @@ -1634,20 +1648,6 @@ char *device_node_string(char *buf, char *end, struct device_node *dn, return widen_string(buf, buf - buf_start, end, spec); } -static noinline_for_stack -char *pointer_string(char *buf, char *end, const void *ptr, - struct printf_spec spec) -{ - spec.base = 16; - spec.flags |= SMALL; - if (spec.field_width == -1) { - spec.field_width = 2 * sizeof(ptr); - spec.flags |= ZEROPAD; - } - - return number(buf, end, (unsigned long int)ptr, spec); -} - static bool have_filled_random_ptr_key __read_mostly; static siphash_key_t ptr_key __read_mostly; From 496a9a5f3806d58b14ae06b390d5b1ffa26e9f9a Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:08 +0200 Subject: [PATCH 06/16] lib/vsprintf: Deduplicate pointer_string() There is an exact code at the end of ptr_to_id(). Replace it by calling pointer_string() directly. This is followup to the commit ad67b74d2469 ("printk: hash addresses printed with %p"). Cc: Tobin C. Harding Link: http://lkml.kernel.org/r/20180216210711.79901-6-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 87dbced51b1a..9004bbb3d84d 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1367,13 +1367,6 @@ static noinline_for_stack char *restricted_pointer(char *buf, char *end, const void *ptr, struct printf_spec spec) { - spec.base = 16; - spec.flags |= SMALL; - if (spec.field_width == -1) { - spec.field_width = 2 * sizeof(ptr); - spec.flags |= ZEROPAD; - } - switch (kptr_restrict) { case 0: /* Always print %pK values */ @@ -1385,8 +1378,11 @@ char *restricted_pointer(char *buf, char *end, const void *ptr, * kptr_restrict==1 cannot be used in IRQ context * because its test for CAP_SYSLOG would be meaningless. */ - if (in_irq() || in_serving_softirq() || in_nmi()) + if (in_irq() || in_serving_softirq() || in_nmi()) { + if (spec.field_width == -1) + spec.field_width = 2 * sizeof(ptr); return string(buf, end, "pK-error", spec); + } /* * Only print the real pointer value if the current @@ -1411,7 +1407,7 @@ char *restricted_pointer(char *buf, char *end, const void *ptr, break; } - return number(buf, end, (unsigned long)ptr, spec); + return pointer_string(buf, end, ptr, spec); } static noinline_for_stack @@ -1686,10 +1682,9 @@ early_initcall(initialize_ptr_random); static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) { unsigned long hashval; - const int default_width = 2 * sizeof(ptr); if (unlikely(!have_filled_random_ptr_key)) { - spec.field_width = default_width; + spec.field_width = 2 * sizeof(ptr); /* string length must be less than default_width */ return string(buf, end, "(ptrval)", spec); } @@ -1704,15 +1699,7 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) #else hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key); #endif - - spec.flags |= SMALL; - if (spec.field_width == -1) { - spec.field_width = default_width; - spec.flags |= ZEROPAD; - } - spec.base = 16; - - return number(buf, end, hashval, spec); + return pointer_string(buf, end, (const void *)hashval, spec); } /* From 91efafb1dd8f471177a3dddb4841d75d3df1cc46 Mon Sep 17 00:00:00 2001 From: Shunyong Yang Date: Fri, 16 Feb 2018 23:07:09 +0200 Subject: [PATCH 07/16] lib/vsprintf: Replace space with '_' before crng is ready Before crng is ready, output of "%p" composes of "(ptrval)" and left padding spaces for alignment as no random address can be generated. This seems a little strange when default string width is larger than strlen("(ptrval)"). For example, when irq domain names are built with "%p", the nodes under /sys/kernel/debug/irq/domains like this on AArch64 system, [root@y irq]# ls domains/ default irqchip@ (ptrval)-2 irqchip@ (ptrval)-4 \_SB_.TCS0.QIC1 \_SB_.TCS0.QIC3 irqchip@ (ptrval) irqchip@ (ptrval)-3 \_SB_.TCS0.QIC0 \_SB_.TCS0.QIC2 The name "irqchip@ (ptrval)-2" is not so readable in console output. This patch replaces space with readable "_" when output needs padding. Following is the output after applying the patch, [root@y domains]# ls default irqchip@(____ptrval____)-2 irqchip@(____ptrval____)-4 \_SB_.TCS0.QIC1 \_SB_.TCS0.QIC3 irqchip@(____ptrval____) irqchip@(____ptrval____)-3 \_SB_.TCS0.QIC0 \_SB_.TCS0.QIC2 There is same problem in some subsystem's dmesg output. Moreover, someone may call "%p" in a similar case. In addition, the timing of crng initialization done may vary on different system. So, the change is made in vsprintf.c. Suggested-by: Rasmus Villemoes Link: http://lkml.kernel.org/r/20180216210711.79901-7-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Cc: Joey Zheng Signed-off-by: Shunyong Yang Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 9004bbb3d84d..97be2d07297a 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1681,12 +1681,13 @@ early_initcall(initialize_ptr_random); /* Maps a pointer to a 32 bit unique identifier. */ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) { + const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)"; unsigned long hashval; if (unlikely(!have_filled_random_ptr_key)) { spec.field_width = 2 * sizeof(ptr); /* string length must be less than default_width */ - return string(buf, end, "(ptrval)", spec); + return string(buf, end, str, spec); } #ifdef CONFIG_64BIT From 7e6bd6f3dcf913460a0a0ae7f260a8280001dd80 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 16 Feb 2018 23:07:11 +0200 Subject: [PATCH 08/16] lib/vsprintf: Mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Link: http://lkml.kernel.org/r/20180216210711.79901-9-andriy.shevchenko@linux.intel.com To: "Tobin C . Harding" To: linux@rasmusvillemoes.dk To: Joe Perches To: linux-kernel@vger.kernel.org To: Andrew Morton Signed-off-by: Andy Shevchenko Signed-off-by: Petr Mladek --- lib/vsprintf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 97be2d07297a..38a71df48d48 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -2092,6 +2092,7 @@ qualifier: case 'x': spec->flags |= SMALL; + /* fall through */ case 'X': spec->base = 16; @@ -3046,8 +3047,10 @@ int vsscanf(const char *buf, const char *fmt, va_list args) break; case 'i': base = 0; + /* fall through */ case 'd': is_sign = true; + /* fall through */ case 'u': break; case '%': From cdb7e52d960a59f30de853f5dd85574432d6bb50 Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Sat, 14 Apr 2018 12:00:05 +0900 Subject: [PATCH 09/16] vsprintf: Tweak pF/pf comment Reflect changes that have happened to pf/pF (deprecation) specifiers in pointer() comment section. Link: http://lkml.kernel.org/r/20180414030005.25831-1-sergey.senozhatsky@gmail.com Cc: Steven Rostedt Cc: Andrew Morton Cc: Joe Perches Cc: linux-kernel@vger.kernel.org Signed-off-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- lib/vsprintf.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 38a71df48d48..7649ef4ed7d0 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1713,10 +1713,10 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) * * Right now we handle: * - * - 'F' For symbolic function descriptor pointers with offset - * - 'f' For simple symbolic function names without offset - * - 'S' For symbolic direct pointers with offset - * - 's' For symbolic direct pointers without offset + * - 'S' For symbolic direct pointers (or function descriptors) with offset + * - 's' For symbolic direct pointers (or function descriptors) without offset + * - 'F' Same as 'S' + * - 'f' Same as 's' * - '[FfSs]R' as above with __builtin_extract_return_addr() translation * - 'B' For backtraced symbolic direct pointers with offset * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref] @@ -1813,10 +1813,6 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) * ** When making changes please also update: * Documentation/core-api/printk-formats.rst * - * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 - * function pointers are really function descriptors, which contain a - * pointer to the real address. - * * Note: The default behaviour (unadorned %p) is to hash the address, * rendering it useful as a unique identifier. */ From 43a17111c2553925f65e7be9b9c3f9d90cf29a8b Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Thu, 19 Apr 2018 10:42:50 +0900 Subject: [PATCH 10/16] printk: wake up klogd in vprintk_emit We wake up klogd very late - only when current console_sem owner is done pushing pending kernel messages to the serial/net consoles. In some cases this results in lost syslog messages, because kernel log buffer is a circular buffer and if we don't wakeup syslog long enough there are chances that logbuf simply will wrap around. The patch moves the klogd wake up call to vprintk_emit(), which is the only legit way for a kernel message to appear in the logbuf, right after the attempt to handle consoles. As a result, klogd will get waken either after flushing the new message to consoles or immediately when consoles are still busy with older messages. Link: http://lkml.kernel.org/r/20180419014250.5692-1-sergey.senozhatsky@gmail.com To: Steven Rostedt Cc: Andrew Morton Cc: Peter Zijlstra Cc: Tejun Heo Cc: linux-kernel@vger.kernel.org Signed-off-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- kernel/printk/printk.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 704e55129c3a..fba995b305b1 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1907,6 +1907,7 @@ asmlinkage int vprintk_emit(int facility, int level, preempt_enable(); } + wake_up_klogd(); return printed_len; } EXPORT_SYMBOL(vprintk_emit); @@ -2288,9 +2289,7 @@ void console_unlock(void) { static char ext_text[CONSOLE_EXT_LOG_MAX]; static char text[LOG_LINE_MAX + PREFIX_MAX]; - static u64 seen_seq; unsigned long flags; - bool wake_klogd = false; bool do_cond_resched, retry; if (console_suspended) { @@ -2334,11 +2333,6 @@ again: printk_safe_enter_irqsave(flags); raw_spin_lock(&logbuf_lock); - if (seen_seq != log_next_seq) { - wake_klogd = true; - seen_seq = log_next_seq; - } - if (console_seq < log_first_seq) { len = sprintf(text, "** %u printk messages dropped **\n", (unsigned)(log_first_seq - console_seq)); @@ -2396,7 +2390,7 @@ skip: if (console_lock_spinning_disable_and_check()) { printk_safe_exit_irqrestore(flags); - goto out; + return; } printk_safe_exit_irqrestore(flags); @@ -2428,10 +2422,6 @@ skip: if (retry && console_trylock()) goto again; - -out: - if (wake_klogd) - wake_up_klogd(); } EXPORT_SYMBOL(console_unlock); From 988a35f8da1dec5a8cd2788054d1e717be61bf25 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Fri, 11 May 2018 19:54:19 +0900 Subject: [PATCH 11/16] printk: fix possible reuse of va_list variable I noticed that there is a possibility that printk_safe_log_store() causes kernel oops because "args" parameter is passed to vsnprintf() again when atomic_cmpxchg() detected that we raced. Fix this by using va_copy(). Link: http://lkml.kernel.org/r/201805112002.GIF21216.OFVHFOMLJtQFSO@I-love.SAKURA.ne.jp Cc: Peter Zijlstra Cc: Steven Rostedt Cc: dvyukov@google.com Cc: syzkaller@googlegroups.com Cc: fengguang.wu@intel.com Cc: linux-kernel@vger.kernel.org Signed-off-by: Tetsuo Handa Fixes: 42a0bb3f71383b45 ("printk/nmi: generic solution for safe printk in NMI") Cc: 4.7+ # v4.7+ Reviewed-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- kernel/printk/printk_safe.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c index 3e3c2004bb23..449d67edfa4b 100644 --- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -82,6 +82,7 @@ static __printf(2, 0) int printk_safe_log_store(struct printk_safe_seq_buf *s, { int add; size_t len; + va_list ap; again: len = atomic_read(&s->len); @@ -100,7 +101,9 @@ again: if (!len) smp_rmb(); - add = vscnprintf(s->buffer + len, sizeof(s->buffer) - len, fmt, args); + va_copy(ap, args); + add = vscnprintf(s->buffer + len, sizeof(s->buffer) - len, fmt, ap); + va_end(ap); if (!add) return 0; From ef4b0be62641d296cf4c0ad8f75ab83ab066ed51 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 1 Jun 2018 11:28:19 +0200 Subject: [PATCH 12/16] clk: renesas: cpg-mssr: Stop using printk format %pCr Printk format "%pCr" will be removed soon, as clk_get_rate() must not be called in atomic context. Replace it by open-coding the operation. This is safe here, as the code runs in task context. Link: http://lkml.kernel.org/r/1527845302-12159-2-git-send-email-geert+renesas@glider.be To: Jia-Ju Bai To: Jonathan Corbet To: Michael Turquette To: Stephen Boyd To: Zhang Rui To: Eduardo Valentin To: Eric Anholt To: Stefan Wahren To: Greg Kroah-Hartman Cc: Sergey Senozhatsky Cc: Petr Mladek Cc: Linus Torvalds Cc: Steven Rostedt Cc: linux-doc@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: linux-serial@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Geert Uytterhoeven Cc: stable@vger.kernel.org # 4.5+ Signed-off-by: Geert Uytterhoeven Acked-by: Stephen Boyd Signed-off-by: Petr Mladek --- drivers/clk/renesas/renesas-cpg-mssr.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index e3cc72c81311..2c9988fef656 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -258,8 +258,9 @@ struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec, dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx, PTR_ERR(clk)); else - dev_dbg(dev, "clock (%u, %u) is %pC at %pCr Hz\n", - clkspec->args[0], clkspec->args[1], clk, clk); + dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n", + clkspec->args[0], clkspec->args[1], clk, + clk_get_rate(clk)); return clk; } @@ -326,7 +327,7 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core, if (IS_ERR_OR_NULL(clk)) goto fail; - dev_dbg(dev, "Core clock %pC at %pCr Hz\n", clk, clk); + dev_dbg(dev, "Core clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); priv->clks[id] = clk; return; @@ -392,7 +393,7 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, if (IS_ERR(clk)) goto fail; - dev_dbg(dev, "Module clock %pC at %pCr Hz\n", clk, clk); + dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk, clk_get_rate(clk)); priv->clks[id] = clk; priv->smstpcr_saved[clock->index / 32].mask |= BIT(clock->index % 32); return; From bd2a07f71a1e2e198f8a30cb551d9defe422d83d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 1 Jun 2018 11:28:20 +0200 Subject: [PATCH 13/16] thermal: bcm2835: Stop using printk format %pCr Printk format "%pCr" will be removed soon, as clk_get_rate() must not be called in atomic context. Replace it by printing the variable that already holds the clock rate. Note that calling clk_get_rate() is safe here, as the code runs in task context. Link: http://lkml.kernel.org/r/1527845302-12159-3-git-send-email-geert+renesas@glider.be To: Jia-Ju Bai To: Jonathan Corbet To: Michael Turquette To: Stephen Boyd To: Zhang Rui To: Eduardo Valentin To: Eric Anholt To: Stefan Wahren To: Greg Kroah-Hartman Cc: Sergey Senozhatsky Cc: Petr Mladek Cc: Linus Torvalds Cc: Steven Rostedt Cc: linux-doc@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: linux-serial@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org # 4.12+ Signed-off-by: Geert Uytterhoeven Acked-by: Stefan Wahren Signed-off-by: Petr Mladek --- drivers/thermal/broadcom/bcm2835_thermal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c index a4d6a0e2e993..23ad4f9f2143 100644 --- a/drivers/thermal/broadcom/bcm2835_thermal.c +++ b/drivers/thermal/broadcom/bcm2835_thermal.c @@ -213,8 +213,8 @@ static int bcm2835_thermal_probe(struct platform_device *pdev) rate = clk_get_rate(data->clk); if ((rate < 1920000) || (rate > 5000000)) dev_warn(&pdev->dev, - "Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz\n", - data->clk, data->clk); + "Clock %pCn running at %lu Hz is outside of the recommended range: 1.92 to 5MHz\n", + data->clk, rate); /* register of thermal sensor and get info from DT */ tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data, From d63c16f8e1ab761775275adcf54f4bef7c330295 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 1 Jun 2018 11:28:21 +0200 Subject: [PATCH 14/16] serial: sh-sci: Stop using printk format %pCr Printk format "%pCr" will be removed soon, as clk_get_rate() must not be called in atomic context. Replace it by open-coding the operation. This is safe here, as the code runs in task context. Link: http://lkml.kernel.org/r/1527845302-12159-4-git-send-email-geert+renesas@glider.be To: Jia-Ju Bai To: Jonathan Corbet To: Michael Turquette To: Stephen Boyd To: Zhang Rui To: Eduardo Valentin To: Eric Anholt To: Stefan Wahren To: Greg Kroah-Hartman Cc: Sergey Senozhatsky Cc: Petr Mladek Cc: Linus Torvalds Cc: Steven Rostedt Cc: linux-doc@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: linux-serial@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Geert Uytterhoeven Cc: stable@vger.kernel.org # 4.5+ Signed-off-by: Geert Uytterhoeven Signed-off-by: Petr Mladek --- drivers/tty/serial/sh-sci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index fdbbff547106..a4f82ec665fe 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -2704,8 +2704,8 @@ found: dev_dbg(dev, "failed to get %s (%ld)\n", clk_names[i], PTR_ERR(clk)); else - dev_dbg(dev, "clk %s is %pC rate %pCr\n", clk_names[i], - clk, clk); + dev_dbg(dev, "clk %s is %pC rate %lu\n", clk_names[i], + clk, clk_get_rate(clk)); sci_port->clks[i] = IS_ERR(clk) ? NULL : clk; } return 0; From 666902e42fd8344b923c02dc5b0f37948ff4f225 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 1 Jun 2018 11:28:22 +0200 Subject: [PATCH 15/16] lib/vsprintf: Remove atomic-unsafe support for %pCr "%pCr" formats the current rate of a clock, and calls clk_get_rate(). The latter obtains a mutex, hence it must not be called from atomic context. Remove support for this rarely-used format, as vsprintf() (and e.g. printk()) must be callable from any context. Any remaining out-of-tree users will start seeing the clock's name printed instead of its rate. Reported-by: Jia-Ju Bai Fixes: 900cca2944254edd ("lib/vsprintf: add %pC{,n,r} format specifiers for clocks") Link: http://lkml.kernel.org/r/1527845302-12159-5-git-send-email-geert+renesas@glider.be To: Jia-Ju Bai To: Jonathan Corbet To: Michael Turquette To: Stephen Boyd To: Zhang Rui To: Eduardo Valentin To: Eric Anholt To: Stefan Wahren To: Greg Kroah-Hartman Cc: Sergey Senozhatsky Cc: Petr Mladek Cc: Linus Torvalds Cc: Steven Rostedt Cc: linux-doc@vger.kernel.org Cc: linux-clk@vger.kernel.org Cc: linux-pm@vger.kernel.org Cc: linux-serial@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: Geert Uytterhoeven Cc: stable@vger.kernel.org # 4.1+ Signed-off-by: Geert Uytterhoeven Signed-off-by: Petr Mladek --- Documentation/core-api/printk-formats.rst | 3 +-- lib/vsprintf.c | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst index eb30efdd2e78..25dc591cb110 100644 --- a/Documentation/core-api/printk-formats.rst +++ b/Documentation/core-api/printk-formats.rst @@ -419,11 +419,10 @@ struct clk %pC pll1 %pCn pll1 - %pCr 1560000000 For printing struct clk structures. %pC and %pCn print the name (Common Clock Framework) or address (legacy clock framework) of the -structure; %pCr prints the current clock rate. +structure. Passed by reference. diff --git a/lib/vsprintf.c b/lib/vsprintf.c index d7a708f82559..8f28036f5c1d 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1446,9 +1446,6 @@ char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec, return string(buf, end, NULL, spec); switch (fmt[1]) { - case 'r': - return number(buf, end, clk_get_rate(clk), spec); - case 'n': default: #ifdef CONFIG_COMMON_CLK From 554755be08fba31c74f66b82a485e5513205af84 Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Wed, 30 May 2018 16:03:50 +0900 Subject: [PATCH 16/16] printk: drop in_nmi check from printk_safe_flush_on_panic() Drop the in_nmi() check from printk_safe_flush_on_panic() and attempt to re-init (IOW unlock) locked logbuf spinlock from panic CPU regardless of its context. Otherwise, theoretically, we can deadlock on logbuf trying to flush per-CPU buffers: a) Panic CPU is running in non-NMI context b) Panic CPU sends out shutdown IPI via reboot vector c) Panic CPU fails to stop all remote CPUs d) Panic CPU sends out shutdown IPI via NMI vector One of the CPUs that we bring down via NMI vector can hold logbuf spin lock (theoretically). Link: http://lkml.kernel.org/r/20180530070350.10131-1-sergey.senozhatsky@gmail.com To: Steven Rostedt Cc: Peter Zijlstra Cc: linux-kernel@vger.kernel.org Signed-off-by: Sergey Senozhatsky Signed-off-by: Petr Mladek --- kernel/printk/printk_safe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c index 449d67edfa4b..d7d091309054 100644 --- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -281,7 +281,7 @@ void printk_safe_flush_on_panic(void) * Make sure that we could access the main ring buffer. * Do not risk a double release when more CPUs are up. */ - if (in_nmi() && raw_spin_is_locked(&logbuf_lock)) { + if (raw_spin_is_locked(&logbuf_lock)) { if (num_online_cpus() > 1) return;