diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-25 20:11:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-25 20:11:52 -0400 |
commit | a67eefad996f007afc7c38efe8f45257fb1e3994 (patch) | |
tree | ad8e92971827bfbb26d34fd49e7633d72f1369e2 | |
parent | 62606c224d72a98c35d21a849f95cccf95b0a252 (diff) | |
parent | 54edeb0327d7320e2a9a3e517e8bc8f318d41a77 (diff) |
Merge tag 'printk-for-4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk
Pull printk updates from Petr Mladek:
- Fix two more locations where printf formatting leaked pointers
- Better log_buf_len parameter handling
- Add prefix to messages from printk code
- Do not miss messages on other consoles when the log is replayed on a
new one
- Reduce race between console registration and panic() when the log
might get replayed on all consoles
- Some cont buffer code clean up
- Call console only when there is something to do (log vs cont buffer)
* tag 'printk-for-4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek/printk:
lib/vsprintf: Hash printed address for netdev bits fallback
lib/vsprintf: Hash legacy clock addresses
lib/vsprintf: Prepare for more general use of ptr_to_id()
lib/vsprintf: Make ptr argument conts in ptr_to_id()
printk: fix integer overflow in setup_log_buf()
printk: do not preliminary split up cont buffer
printk: lock/unlock console only for new logbuf entries
printk: keep kernel cont support always enabled
printk: Give error on attempt to set log buffer length to over 2G
printk: Add KBUILD_MODNAME and remove a redundant print prefix
printk: Correct wrong casting
printk: Fix panic caused by passing log_buf_len to command line
printk: CON_PRINTBUFFER console registration is a bit racy
printk: Do not miss new messages when replaying the log
-rw-r--r-- | Documentation/core-api/printk-formats.rst | 5 | ||||
-rw-r--r-- | kernel/printk/printk.c | 86 | ||||
-rw-r--r-- | lib/vsprintf.c | 216 |
3 files changed, 158 insertions, 149 deletions
diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst index 86023c33906f..ff48b55040ef 100644 --- a/Documentation/core-api/printk-formats.rst +++ b/Documentation/core-api/printk-formats.rst | |||
@@ -420,9 +420,8 @@ struct clk | |||
420 | %pC pll1 | 420 | %pC pll1 |
421 | %pCn pll1 | 421 | %pCn pll1 |
422 | 422 | ||
423 | For printing struct clk structures. %pC and %pCn print the name | 423 | For printing struct clk structures. %pC and %pCn print the name of the clock |
424 | (Common Clock Framework) or address (legacy clock framework) of the | 424 | (Common Clock Framework) or a unique 32-bit ID (legacy clock framework). |
425 | structure. | ||
426 | 425 | ||
427 | Passed by reference. | 426 | Passed by reference. |
428 | 427 | ||
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 9bf5404397e0..b77150ad1965 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c | |||
@@ -16,6 +16,8 @@ | |||
16 | * 01Mar01 Andrew Morton | 16 | * 01Mar01 Andrew Morton |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
20 | |||
19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
20 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
21 | #include <linux/tty.h> | 23 | #include <linux/tty.h> |
@@ -192,16 +194,7 @@ int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write, | |||
192 | return 0; | 194 | return 0; |
193 | } | 195 | } |
194 | 196 | ||
195 | /* | 197 | /* Number of registered extended console drivers. */ |
196 | * Number of registered extended console drivers. | ||
197 | * | ||
198 | * If extended consoles are present, in-kernel cont reassembly is disabled | ||
199 | * and each fragment is stored as a separate log entry with proper | ||
200 | * continuation flag so that every emitted message has full metadata. This | ||
201 | * doesn't change the result for regular consoles or /proc/kmsg. For | ||
202 | * /dev/kmsg, as long as the reader concatenates messages according to | ||
203 | * consecutive continuation flags, the end result should be the same too. | ||
204 | */ | ||
205 | static int nr_ext_console_drivers; | 198 | static int nr_ext_console_drivers; |
206 | 199 | ||
207 | /* | 200 | /* |
@@ -423,6 +416,7 @@ static u32 log_next_idx; | |||
423 | /* the next printk record to write to the console */ | 416 | /* the next printk record to write to the console */ |
424 | static u64 console_seq; | 417 | static u64 console_seq; |
425 | static u32 console_idx; | 418 | static u32 console_idx; |
419 | static u64 exclusive_console_stop_seq; | ||
426 | 420 | ||
427 | /* the next printk record to read after the last 'clear' command */ | 421 | /* the next printk record to read after the last 'clear' command */ |
428 | static u64 clear_seq; | 422 | static u64 clear_seq; |
@@ -437,6 +431,7 @@ static u32 clear_idx; | |||
437 | /* record buffer */ | 431 | /* record buffer */ |
438 | #define LOG_ALIGN __alignof__(struct printk_log) | 432 | #define LOG_ALIGN __alignof__(struct printk_log) |
439 | #define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT) | 433 | #define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT) |
434 | #define LOG_BUF_LEN_MAX (u32)(1 << 31) | ||
440 | static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN); | 435 | static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN); |
441 | static char *log_buf = __log_buf; | 436 | static char *log_buf = __log_buf; |
442 | static u32 log_buf_len = __LOG_BUF_LEN; | 437 | static u32 log_buf_len = __LOG_BUF_LEN; |
@@ -1037,18 +1032,28 @@ void log_buf_vmcoreinfo_setup(void) | |||
1037 | static unsigned long __initdata new_log_buf_len; | 1032 | static unsigned long __initdata new_log_buf_len; |
1038 | 1033 | ||
1039 | /* we practice scaling the ring buffer by powers of 2 */ | 1034 | /* we practice scaling the ring buffer by powers of 2 */ |
1040 | static void __init log_buf_len_update(unsigned size) | 1035 | static void __init log_buf_len_update(u64 size) |
1041 | { | 1036 | { |
1037 | if (size > (u64)LOG_BUF_LEN_MAX) { | ||
1038 | size = (u64)LOG_BUF_LEN_MAX; | ||
1039 | pr_err("log_buf over 2G is not supported.\n"); | ||
1040 | } | ||
1041 | |||
1042 | if (size) | 1042 | if (size) |
1043 | size = roundup_pow_of_two(size); | 1043 | size = roundup_pow_of_two(size); |
1044 | if (size > log_buf_len) | 1044 | if (size > log_buf_len) |
1045 | new_log_buf_len = size; | 1045 | new_log_buf_len = (unsigned long)size; |
1046 | } | 1046 | } |
1047 | 1047 | ||
1048 | /* save requested log_buf_len since it's too early to process it */ | 1048 | /* save requested log_buf_len since it's too early to process it */ |
1049 | static int __init log_buf_len_setup(char *str) | 1049 | static int __init log_buf_len_setup(char *str) |
1050 | { | 1050 | { |
1051 | unsigned size = memparse(str, &str); | 1051 | u64 size; |
1052 | |||
1053 | if (!str) | ||
1054 | return -EINVAL; | ||
1055 | |||
1056 | size = memparse(str, &str); | ||
1052 | 1057 | ||
1053 | log_buf_len_update(size); | 1058 | log_buf_len_update(size); |
1054 | 1059 | ||
@@ -1093,7 +1098,7 @@ void __init setup_log_buf(int early) | |||
1093 | { | 1098 | { |
1094 | unsigned long flags; | 1099 | unsigned long flags; |
1095 | char *new_log_buf; | 1100 | char *new_log_buf; |
1096 | int free; | 1101 | unsigned int free; |
1097 | 1102 | ||
1098 | if (log_buf != __log_buf) | 1103 | if (log_buf != __log_buf) |
1099 | return; | 1104 | return; |
@@ -1113,7 +1118,7 @@ void __init setup_log_buf(int early) | |||
1113 | } | 1118 | } |
1114 | 1119 | ||
1115 | if (unlikely(!new_log_buf)) { | 1120 | if (unlikely(!new_log_buf)) { |
1116 | pr_err("log_buf_len: %ld bytes not available\n", | 1121 | pr_err("log_buf_len: %lu bytes not available\n", |
1117 | new_log_buf_len); | 1122 | new_log_buf_len); |
1118 | return; | 1123 | return; |
1119 | } | 1124 | } |
@@ -1126,8 +1131,8 @@ void __init setup_log_buf(int early) | |||
1126 | memcpy(log_buf, __log_buf, __LOG_BUF_LEN); | 1131 | memcpy(log_buf, __log_buf, __LOG_BUF_LEN); |
1127 | logbuf_unlock_irqrestore(flags); | 1132 | logbuf_unlock_irqrestore(flags); |
1128 | 1133 | ||
1129 | pr_info("log_buf_len: %d bytes\n", log_buf_len); | 1134 | pr_info("log_buf_len: %u bytes\n", log_buf_len); |
1130 | pr_info("early log buf free: %d(%d%%)\n", | 1135 | pr_info("early log buf free: %u(%u%%)\n", |
1131 | free, (free * 100) / __LOG_BUF_LEN); | 1136 | free, (free * 100) / __LOG_BUF_LEN); |
1132 | } | 1137 | } |
1133 | 1138 | ||
@@ -1767,12 +1772,8 @@ static void cont_flush(void) | |||
1767 | 1772 | ||
1768 | static bool cont_add(int facility, int level, enum log_flags flags, const char *text, size_t len) | 1773 | static bool cont_add(int facility, int level, enum log_flags flags, const char *text, size_t len) |
1769 | { | 1774 | { |
1770 | /* | 1775 | /* If the line gets too long, split it up in separate records. */ |
1771 | * If ext consoles are present, flush and skip in-kernel | 1776 | if (cont.len + len > sizeof(cont.buf)) { |
1772 | * continuation. See nr_ext_console_drivers definition. Also, if | ||
1773 | * the line gets too long, split it up in separate records. | ||
1774 | */ | ||
1775 | if (nr_ext_console_drivers || cont.len + len > sizeof(cont.buf)) { | ||
1776 | cont_flush(); | 1777 | cont_flush(); |
1777 | return false; | 1778 | return false; |
1778 | } | 1779 | } |
@@ -1795,9 +1796,6 @@ static bool cont_add(int facility, int level, enum log_flags flags, const char * | |||
1795 | cont_flush(); | 1796 | cont_flush(); |
1796 | } | 1797 | } |
1797 | 1798 | ||
1798 | if (cont.len > (sizeof(cont.buf) * 80) / 100) | ||
1799 | cont_flush(); | ||
1800 | |||
1801 | return true; | 1799 | return true; |
1802 | } | 1800 | } |
1803 | 1801 | ||
@@ -1889,8 +1887,9 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1889 | const char *fmt, va_list args) | 1887 | const char *fmt, va_list args) |
1890 | { | 1888 | { |
1891 | int printed_len; | 1889 | int printed_len; |
1892 | bool in_sched = false; | 1890 | bool in_sched = false, pending_output; |
1893 | unsigned long flags; | 1891 | unsigned long flags; |
1892 | u64 curr_log_seq; | ||
1894 | 1893 | ||
1895 | if (level == LOGLEVEL_SCHED) { | 1894 | if (level == LOGLEVEL_SCHED) { |
1896 | level = LOGLEVEL_DEFAULT; | 1895 | level = LOGLEVEL_DEFAULT; |
@@ -1902,11 +1901,13 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1902 | 1901 | ||
1903 | /* This stops the holder of console_sem just where we want him */ | 1902 | /* This stops the holder of console_sem just where we want him */ |
1904 | logbuf_lock_irqsave(flags); | 1903 | logbuf_lock_irqsave(flags); |
1904 | curr_log_seq = log_next_seq; | ||
1905 | printed_len = vprintk_store(facility, level, dict, dictlen, fmt, args); | 1905 | printed_len = vprintk_store(facility, level, dict, dictlen, fmt, args); |
1906 | pending_output = (curr_log_seq != log_next_seq); | ||
1906 | logbuf_unlock_irqrestore(flags); | 1907 | logbuf_unlock_irqrestore(flags); |
1907 | 1908 | ||
1908 | /* If called from the scheduler, we can not call up(). */ | 1909 | /* If called from the scheduler, we can not call up(). */ |
1909 | if (!in_sched) { | 1910 | if (!in_sched && pending_output) { |
1910 | /* | 1911 | /* |
1911 | * Disable preemption to avoid being preempted while holding | 1912 | * Disable preemption to avoid being preempted while holding |
1912 | * console_sem which would prevent anyone from printing to | 1913 | * console_sem which would prevent anyone from printing to |
@@ -1923,7 +1924,8 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1923 | preempt_enable(); | 1924 | preempt_enable(); |
1924 | } | 1925 | } |
1925 | 1926 | ||
1926 | wake_up_klogd(); | 1927 | if (pending_output) |
1928 | wake_up_klogd(); | ||
1927 | return printed_len; | 1929 | return printed_len; |
1928 | } | 1930 | } |
1929 | EXPORT_SYMBOL(vprintk_emit); | 1931 | EXPORT_SYMBOL(vprintk_emit); |
@@ -2009,6 +2011,7 @@ static u64 syslog_seq; | |||
2009 | static u32 syslog_idx; | 2011 | static u32 syslog_idx; |
2010 | static u64 console_seq; | 2012 | static u64 console_seq; |
2011 | static u32 console_idx; | 2013 | static u32 console_idx; |
2014 | static u64 exclusive_console_stop_seq; | ||
2012 | static u64 log_first_seq; | 2015 | static u64 log_first_seq; |
2013 | static u32 log_first_idx; | 2016 | static u32 log_first_idx; |
2014 | static u64 log_next_seq; | 2017 | static u64 log_next_seq; |
@@ -2351,8 +2354,9 @@ again: | |||
2351 | printk_safe_enter_irqsave(flags); | 2354 | printk_safe_enter_irqsave(flags); |
2352 | raw_spin_lock(&logbuf_lock); | 2355 | raw_spin_lock(&logbuf_lock); |
2353 | if (console_seq < log_first_seq) { | 2356 | if (console_seq < log_first_seq) { |
2354 | len = sprintf(text, "** %u printk messages dropped **\n", | 2357 | len = sprintf(text, |
2355 | (unsigned)(log_first_seq - console_seq)); | 2358 | "** %llu printk messages dropped **\n", |
2359 | log_first_seq - console_seq); | ||
2356 | 2360 | ||
2357 | /* messages are gone, move to first one */ | 2361 | /* messages are gone, move to first one */ |
2358 | console_seq = log_first_seq; | 2362 | console_seq = log_first_seq; |
@@ -2376,6 +2380,12 @@ skip: | |||
2376 | goto skip; | 2380 | goto skip; |
2377 | } | 2381 | } |
2378 | 2382 | ||
2383 | /* Output to all consoles once old messages replayed. */ | ||
2384 | if (unlikely(exclusive_console && | ||
2385 | console_seq >= exclusive_console_stop_seq)) { | ||
2386 | exclusive_console = NULL; | ||
2387 | } | ||
2388 | |||
2379 | len += msg_print_text(msg, | 2389 | len += msg_print_text(msg, |
2380 | console_msg_format & MSG_FORMAT_SYSLOG, | 2390 | console_msg_format & MSG_FORMAT_SYSLOG, |
2381 | text + len, | 2391 | text + len, |
@@ -2418,10 +2428,6 @@ skip: | |||
2418 | 2428 | ||
2419 | console_locked = 0; | 2429 | console_locked = 0; |
2420 | 2430 | ||
2421 | /* Release the exclusive_console once it is used */ | ||
2422 | if (unlikely(exclusive_console)) | ||
2423 | exclusive_console = NULL; | ||
2424 | |||
2425 | raw_spin_unlock(&logbuf_lock); | 2431 | raw_spin_unlock(&logbuf_lock); |
2426 | 2432 | ||
2427 | up_console_sem(); | 2433 | up_console_sem(); |
@@ -2688,8 +2694,7 @@ void register_console(struct console *newcon) | |||
2688 | } | 2694 | } |
2689 | 2695 | ||
2690 | if (newcon->flags & CON_EXTENDED) | 2696 | if (newcon->flags & CON_EXTENDED) |
2691 | if (!nr_ext_console_drivers++) | 2697 | nr_ext_console_drivers++; |
2692 | pr_info("printk: continuation disabled due to ext consoles, expect more fragments in /dev/kmsg\n"); | ||
2693 | 2698 | ||
2694 | if (newcon->flags & CON_PRINTBUFFER) { | 2699 | if (newcon->flags & CON_PRINTBUFFER) { |
2695 | /* | 2700 | /* |
@@ -2699,13 +2704,18 @@ void register_console(struct console *newcon) | |||
2699 | logbuf_lock_irqsave(flags); | 2704 | logbuf_lock_irqsave(flags); |
2700 | console_seq = syslog_seq; | 2705 | console_seq = syslog_seq; |
2701 | console_idx = syslog_idx; | 2706 | console_idx = syslog_idx; |
2702 | logbuf_unlock_irqrestore(flags); | ||
2703 | /* | 2707 | /* |
2704 | * We're about to replay the log buffer. Only do this to the | 2708 | * We're about to replay the log buffer. Only do this to the |
2705 | * just-registered console to avoid excessive message spam to | 2709 | * just-registered console to avoid excessive message spam to |
2706 | * the already-registered consoles. | 2710 | * the already-registered consoles. |
2711 | * | ||
2712 | * Set exclusive_console with disabled interrupts to reduce | ||
2713 | * race window with eventual console_flush_on_panic() that | ||
2714 | * ignores console_lock. | ||
2707 | */ | 2715 | */ |
2708 | exclusive_console = newcon; | 2716 | exclusive_console = newcon; |
2717 | exclusive_console_stop_seq = console_seq; | ||
2718 | logbuf_unlock_irqrestore(flags); | ||
2709 | } | 2719 | } |
2710 | console_unlock(); | 2720 | console_unlock(); |
2711 | console_sysfs_notify(); | 2721 | console_sysfs_notify(); |
diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 376de10929b3..ad4fbe5bc730 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c | |||
@@ -613,6 +613,109 @@ char *string(char *buf, char *end, const char *s, struct printf_spec spec) | |||
613 | } | 613 | } |
614 | 614 | ||
615 | static noinline_for_stack | 615 | static noinline_for_stack |
616 | char *pointer_string(char *buf, char *end, const void *ptr, | ||
617 | struct printf_spec spec) | ||
618 | { | ||
619 | spec.base = 16; | ||
620 | spec.flags |= SMALL; | ||
621 | if (spec.field_width == -1) { | ||
622 | spec.field_width = 2 * sizeof(ptr); | ||
623 | spec.flags |= ZEROPAD; | ||
624 | } | ||
625 | |||
626 | return number(buf, end, (unsigned long int)ptr, spec); | ||
627 | } | ||
628 | |||
629 | /* Make pointers available for printing early in the boot sequence. */ | ||
630 | static int debug_boot_weak_hash __ro_after_init; | ||
631 | |||
632 | static int __init debug_boot_weak_hash_enable(char *str) | ||
633 | { | ||
634 | debug_boot_weak_hash = 1; | ||
635 | pr_info("debug_boot_weak_hash enabled\n"); | ||
636 | return 0; | ||
637 | } | ||
638 | early_param("debug_boot_weak_hash", debug_boot_weak_hash_enable); | ||
639 | |||
640 | static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key); | ||
641 | static siphash_key_t ptr_key __read_mostly; | ||
642 | |||
643 | static void enable_ptr_key_workfn(struct work_struct *work) | ||
644 | { | ||
645 | get_random_bytes(&ptr_key, sizeof(ptr_key)); | ||
646 | /* Needs to run from preemptible context */ | ||
647 | static_branch_disable(¬_filled_random_ptr_key); | ||
648 | } | ||
649 | |||
650 | static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn); | ||
651 | |||
652 | static void fill_random_ptr_key(struct random_ready_callback *unused) | ||
653 | { | ||
654 | /* This may be in an interrupt handler. */ | ||
655 | queue_work(system_unbound_wq, &enable_ptr_key_work); | ||
656 | } | ||
657 | |||
658 | static struct random_ready_callback random_ready = { | ||
659 | .func = fill_random_ptr_key | ||
660 | }; | ||
661 | |||
662 | static int __init initialize_ptr_random(void) | ||
663 | { | ||
664 | int key_size = sizeof(ptr_key); | ||
665 | int ret; | ||
666 | |||
667 | /* Use hw RNG if available. */ | ||
668 | if (get_random_bytes_arch(&ptr_key, key_size) == key_size) { | ||
669 | static_branch_disable(¬_filled_random_ptr_key); | ||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | ret = add_random_ready_callback(&random_ready); | ||
674 | if (!ret) { | ||
675 | return 0; | ||
676 | } else if (ret == -EALREADY) { | ||
677 | /* This is in preemptible context */ | ||
678 | enable_ptr_key_workfn(&enable_ptr_key_work); | ||
679 | return 0; | ||
680 | } | ||
681 | |||
682 | return ret; | ||
683 | } | ||
684 | early_initcall(initialize_ptr_random); | ||
685 | |||
686 | /* Maps a pointer to a 32 bit unique identifier. */ | ||
687 | static char *ptr_to_id(char *buf, char *end, const void *ptr, | ||
688 | struct printf_spec spec) | ||
689 | { | ||
690 | const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)"; | ||
691 | unsigned long hashval; | ||
692 | |||
693 | /* When debugging early boot use non-cryptographically secure hash. */ | ||
694 | if (unlikely(debug_boot_weak_hash)) { | ||
695 | hashval = hash_long((unsigned long)ptr, 32); | ||
696 | return pointer_string(buf, end, (const void *)hashval, spec); | ||
697 | } | ||
698 | |||
699 | if (static_branch_unlikely(¬_filled_random_ptr_key)) { | ||
700 | spec.field_width = 2 * sizeof(ptr); | ||
701 | /* string length must be less than default_width */ | ||
702 | return string(buf, end, str, spec); | ||
703 | } | ||
704 | |||
705 | #ifdef CONFIG_64BIT | ||
706 | hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key); | ||
707 | /* | ||
708 | * Mask off the first 32 bits, this makes explicit that we have | ||
709 | * modified the address (and 32 bits is plenty for a unique ID). | ||
710 | */ | ||
711 | hashval = hashval & 0xffffffff; | ||
712 | #else | ||
713 | hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key); | ||
714 | #endif | ||
715 | return pointer_string(buf, end, (const void *)hashval, spec); | ||
716 | } | ||
717 | |||
718 | static noinline_for_stack | ||
616 | char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec, | 719 | char *dentry_name(char *buf, char *end, const struct dentry *d, struct printf_spec spec, |
617 | const char *fmt) | 720 | const char *fmt) |
618 | { | 721 | { |
@@ -1357,20 +1460,6 @@ char *uuid_string(char *buf, char *end, const u8 *addr, | |||
1357 | return string(buf, end, uuid, spec); | 1460 | return string(buf, end, uuid, spec); |
1358 | } | 1461 | } |
1359 | 1462 | ||
1360 | static noinline_for_stack | ||
1361 | char *pointer_string(char *buf, char *end, const void *ptr, | ||
1362 | struct printf_spec spec) | ||
1363 | { | ||
1364 | spec.base = 16; | ||
1365 | spec.flags |= SMALL; | ||
1366 | if (spec.field_width == -1) { | ||
1367 | spec.field_width = 2 * sizeof(ptr); | ||
1368 | spec.flags |= ZEROPAD; | ||
1369 | } | ||
1370 | |||
1371 | return number(buf, end, (unsigned long int)ptr, spec); | ||
1372 | } | ||
1373 | |||
1374 | int kptr_restrict __read_mostly; | 1463 | int kptr_restrict __read_mostly; |
1375 | 1464 | ||
1376 | static noinline_for_stack | 1465 | static noinline_for_stack |
@@ -1421,7 +1510,8 @@ char *restricted_pointer(char *buf, char *end, const void *ptr, | |||
1421 | } | 1510 | } |
1422 | 1511 | ||
1423 | static noinline_for_stack | 1512 | static noinline_for_stack |
1424 | char *netdev_bits(char *buf, char *end, const void *addr, const char *fmt) | 1513 | char *netdev_bits(char *buf, char *end, const void *addr, |
1514 | struct printf_spec spec, const char *fmt) | ||
1425 | { | 1515 | { |
1426 | unsigned long long num; | 1516 | unsigned long long num; |
1427 | int size; | 1517 | int size; |
@@ -1432,9 +1522,7 @@ char *netdev_bits(char *buf, char *end, const void *addr, const char *fmt) | |||
1432 | size = sizeof(netdev_features_t); | 1522 | size = sizeof(netdev_features_t); |
1433 | break; | 1523 | break; |
1434 | default: | 1524 | default: |
1435 | num = (unsigned long)addr; | 1525 | return ptr_to_id(buf, end, addr, spec); |
1436 | size = sizeof(unsigned long); | ||
1437 | break; | ||
1438 | } | 1526 | } |
1439 | 1527 | ||
1440 | return special_hex_number(buf, end, num, size); | 1528 | return special_hex_number(buf, end, num, size); |
@@ -1474,7 +1562,7 @@ char *clock(char *buf, char *end, struct clk *clk, struct printf_spec spec, | |||
1474 | #ifdef CONFIG_COMMON_CLK | 1562 | #ifdef CONFIG_COMMON_CLK |
1475 | return string(buf, end, __clk_get_name(clk), spec); | 1563 | return string(buf, end, __clk_get_name(clk), spec); |
1476 | #else | 1564 | #else |
1477 | return special_hex_number(buf, end, (unsigned long)clk, sizeof(unsigned long)); | 1565 | return ptr_to_id(buf, end, clk, spec); |
1478 | #endif | 1566 | #endif |
1479 | } | 1567 | } |
1480 | } | 1568 | } |
@@ -1651,94 +1739,6 @@ char *device_node_string(char *buf, char *end, struct device_node *dn, | |||
1651 | return widen_string(buf, buf - buf_start, end, spec); | 1739 | return widen_string(buf, buf - buf_start, end, spec); |
1652 | } | 1740 | } |
1653 | 1741 | ||
1654 | /* Make pointers available for printing early in the boot sequence. */ | ||
1655 | static int debug_boot_weak_hash __ro_after_init; | ||
1656 | |||
1657 | static int __init debug_boot_weak_hash_enable(char *str) | ||
1658 | { | ||
1659 | debug_boot_weak_hash = 1; | ||
1660 | pr_info("debug_boot_weak_hash enabled\n"); | ||
1661 | return 0; | ||
1662 | } | ||
1663 | early_param("debug_boot_weak_hash", debug_boot_weak_hash_enable); | ||
1664 | |||
1665 | static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key); | ||
1666 | static siphash_key_t ptr_key __read_mostly; | ||
1667 | |||
1668 | static void enable_ptr_key_workfn(struct work_struct *work) | ||
1669 | { | ||
1670 | get_random_bytes(&ptr_key, sizeof(ptr_key)); | ||
1671 | /* Needs to run from preemptible context */ | ||
1672 | static_branch_disable(¬_filled_random_ptr_key); | ||
1673 | } | ||
1674 | |||
1675 | static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn); | ||
1676 | |||
1677 | static void fill_random_ptr_key(struct random_ready_callback *unused) | ||
1678 | { | ||
1679 | /* This may be in an interrupt handler. */ | ||
1680 | queue_work(system_unbound_wq, &enable_ptr_key_work); | ||
1681 | } | ||
1682 | |||
1683 | static struct random_ready_callback random_ready = { | ||
1684 | .func = fill_random_ptr_key | ||
1685 | }; | ||
1686 | |||
1687 | static int __init initialize_ptr_random(void) | ||
1688 | { | ||
1689 | int key_size = sizeof(ptr_key); | ||
1690 | int ret; | ||
1691 | |||
1692 | /* Use hw RNG if available. */ | ||
1693 | if (get_random_bytes_arch(&ptr_key, key_size) == key_size) { | ||
1694 | static_branch_disable(¬_filled_random_ptr_key); | ||
1695 | return 0; | ||
1696 | } | ||
1697 | |||
1698 | ret = add_random_ready_callback(&random_ready); | ||
1699 | if (!ret) { | ||
1700 | return 0; | ||
1701 | } else if (ret == -EALREADY) { | ||
1702 | /* This is in preemptible context */ | ||
1703 | enable_ptr_key_workfn(&enable_ptr_key_work); | ||
1704 | return 0; | ||
1705 | } | ||
1706 | |||
1707 | return ret; | ||
1708 | } | ||
1709 | early_initcall(initialize_ptr_random); | ||
1710 | |||
1711 | /* Maps a pointer to a 32 bit unique identifier. */ | ||
1712 | static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) | ||
1713 | { | ||
1714 | const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)"; | ||
1715 | unsigned long hashval; | ||
1716 | |||
1717 | /* When debugging early boot use non-cryptographically secure hash. */ | ||
1718 | if (unlikely(debug_boot_weak_hash)) { | ||
1719 | hashval = hash_long((unsigned long)ptr, 32); | ||
1720 | return pointer_string(buf, end, (const void *)hashval, spec); | ||
1721 | } | ||
1722 | |||
1723 | if (static_branch_unlikely(¬_filled_random_ptr_key)) { | ||
1724 | spec.field_width = 2 * sizeof(ptr); | ||
1725 | /* string length must be less than default_width */ | ||
1726 | return string(buf, end, str, spec); | ||
1727 | } | ||
1728 | |||
1729 | #ifdef CONFIG_64BIT | ||
1730 | hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key); | ||
1731 | /* | ||
1732 | * Mask off the first 32 bits, this makes explicit that we have | ||
1733 | * modified the address (and 32 bits is plenty for a unique ID). | ||
1734 | */ | ||
1735 | hashval = hashval & 0xffffffff; | ||
1736 | #else | ||
1737 | hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key); | ||
1738 | #endif | ||
1739 | return pointer_string(buf, end, (const void *)hashval, spec); | ||
1740 | } | ||
1741 | |||
1742 | /* | 1742 | /* |
1743 | * Show a '%p' thing. A kernel extension is that the '%p' is followed | 1743 | * Show a '%p' thing. A kernel extension is that the '%p' is followed |
1744 | * by an extra set of alphanumeric characters that are extended format | 1744 | * by an extra set of alphanumeric characters that are extended format |
@@ -1942,7 +1942,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, | |||
1942 | break; | 1942 | break; |
1943 | return restricted_pointer(buf, end, ptr, spec); | 1943 | return restricted_pointer(buf, end, ptr, spec); |
1944 | case 'N': | 1944 | case 'N': |
1945 | return netdev_bits(buf, end, ptr, fmt); | 1945 | return netdev_bits(buf, end, ptr, spec, fmt); |
1946 | case 'a': | 1946 | case 'a': |
1947 | return address_val(buf, end, ptr, fmt); | 1947 | return address_val(buf, end, ptr, fmt); |
1948 | case 'd': | 1948 | case 'd': |