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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'printk-for-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux

Pull printk updates from Petr Mladek:

- Add new "hash_pointers=[auto|always|never]" boot parameter to force
the hashing even with "slab_debug" enabled

- Allow to stop CPU, after losing nbcon console ownership during
panic(), even without proper NMI

- Allow to use the printk kthread immediately even for the 1st
registered nbcon

- Compiler warning removal

* tag 'printk-for-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux:
printk: nbcon: Allow reacquire during panic
printk: Allow to use the printk kthread immediately even for 1st nbcon
slab: Decouple slab_debug and no_hash_pointers
vsprintf: Use __diag macros to disable '-Wsuggest-attribute=format'
compiler-gcc.h: Introduce __diag_GCC_all

+170 -58
+26 -12
Documentation/admin-guide/kernel-parameters.txt
··· 1828 1828 backtraces on all cpus. 1829 1829 Format: 0 | 1 1830 1830 1831 + hash_pointers= 1832 + [KNL,EARLY] 1833 + By default, when pointers are printed to the console 1834 + or buffers via the %p format string, that pointer is 1835 + "hashed", i.e. obscured by hashing the pointer value. 1836 + This is a security feature that hides actual kernel 1837 + addresses from unprivileged users, but it also makes 1838 + debugging the kernel more difficult since unequal 1839 + pointers can no longer be compared. The choices are: 1840 + Format: { auto | always | never } 1841 + Default: auto 1842 + 1843 + auto - Hash pointers unless slab_debug is enabled. 1844 + always - Always hash pointers (even if slab_debug is 1845 + enabled). 1846 + never - Never hash pointers. This option should only 1847 + be specified when debugging the kernel. Do 1848 + not use on production kernels. The boot 1849 + param "no_hash_pointers" is an alias for 1850 + this mode. 1851 + 1831 1852 hashdist= [KNL,NUMA] Large hashes allocated during boot 1832 1853 are distributed across NUMA nodes. Defaults on 1833 1854 for 64-bit NUMA, off otherwise. ··· 4237 4216 4238 4217 no_hash_pointers 4239 4218 [KNL,EARLY] 4240 - Force pointers printed to the console or buffers to be 4241 - unhashed. By default, when a pointer is printed via %p 4242 - format string, that pointer is "hashed", i.e. obscured 4243 - by hashing the pointer value. This is a security feature 4244 - that hides actual kernel addresses from unprivileged 4245 - users, but it also makes debugging the kernel more 4246 - difficult since unequal pointers can no longer be 4247 - compared. However, if this command-line option is 4248 - specified, then all normal pointers will have their true 4249 - value printed. This option should only be specified when 4250 - debugging the kernel. Please do not use on production 4251 - kernels. 4219 + Alias for "hash_pointers=never". 4252 4220 4253 4221 nohibernate [HIBERNATION] Disable hibernation and resume. 4254 4222 ··· 6653 6643 last alloc / free. For more information see 6654 6644 Documentation/admin-guide/mm/slab.rst. 6655 6645 (slub_debug legacy name also accepted for now) 6646 + 6647 + Using this option implies the "no_hash_pointers" 6648 + option which can be undone by adding the 6649 + "hash_pointers=always" option. 6656 6650 6657 6651 slab_max_order= [MM] 6658 6652 Determines the maximum allowed order for slabs.
+2
include/linux/compiler-gcc.h
··· 127 127 #define __diag_GCC_8(s) 128 128 #endif 129 129 130 + #define __diag_GCC_all(s) __diag(s) 131 + 130 132 #define __diag_ignore_all(option, comment) \ 131 133 __diag(__diag_GCC_ignore option) 132 134
+1 -1
include/linux/sprintf.h
··· 23 23 24 24 /* These are for specific cases, do not use without real need */ 25 25 extern bool no_hash_pointers; 26 - int no_hash_pointers_enable(char *str); 26 + void hash_pointers_finalize(bool slub_debug); 27 27 28 28 /* Used for Rust formatting ('%pA') */ 29 29 char *rust_fmt_argument(char *buf, char *end, const void *ptr);
+2
kernel/printk/internal.h
··· 64 64 65 65 extern struct printk_ringbuffer *prb; 66 66 extern bool printk_kthreads_running; 67 + extern bool printk_kthreads_ready; 67 68 extern bool debug_non_panic_cpus; 68 69 69 70 __printf(4, 0) ··· 180 179 #define PRINTKRB_RECORD_MAX 0 181 180 182 181 #define printk_kthreads_running (false) 182 + #define printk_kthreads_ready (false) 183 183 184 184 /* 185 185 * In !PRINTK builds we still export console_sem
+65 -24
kernel/printk/nbcon.c
··· 214 214 215 215 /** 216 216 * nbcon_context_try_acquire_direct - Try to acquire directly 217 - * @ctxt: The context of the caller 218 - * @cur: The current console state 217 + * @ctxt: The context of the caller 218 + * @cur: The current console state 219 + * @is_reacquire: This acquire is a reacquire 219 220 * 220 221 * Acquire the console when it is released. Also acquire the console when 221 222 * the current owner has a lower priority and the console is in a safe state. ··· 226 225 * 227 226 * Errors: 228 227 * 229 - * -EPERM: A panic is in progress and this is not the panic CPU. 230 - * Or the current owner or waiter has the same or higher 231 - * priority. No acquire method can be successful in 232 - * this case. 228 + * -EPERM: A panic is in progress and this is neither the panic 229 + * CPU nor is this a reacquire. Or the current owner or 230 + * waiter has the same or higher priority. No acquire 231 + * method can be successful in these cases. 233 232 * 234 233 * -EBUSY: The current owner has a lower priority but the console 235 234 * in an unsafe state. The caller should try using 236 235 * the handover acquire method. 237 236 */ 238 237 static int nbcon_context_try_acquire_direct(struct nbcon_context *ctxt, 239 - struct nbcon_state *cur) 238 + struct nbcon_state *cur, bool is_reacquire) 240 239 { 241 240 unsigned int cpu = smp_processor_id(); 242 241 struct console *con = ctxt->console; ··· 244 243 245 244 do { 246 245 /* 247 - * Panic does not imply that the console is owned. However, it 248 - * is critical that non-panic CPUs during panic are unable to 249 - * acquire ownership in order to satisfy the assumptions of 250 - * nbcon_waiter_matches(). In particular, the assumption that 251 - * lower priorities are ignored during panic. 246 + * Panic does not imply that the console is owned. However, 247 + * since all non-panic CPUs are stopped during panic(), it 248 + * is safer to have them avoid gaining console ownership. 249 + * 250 + * If this acquire is a reacquire (and an unsafe takeover 251 + * has not previously occurred) then it is allowed to attempt 252 + * a direct acquire in panic. This gives console drivers an 253 + * opportunity to perform any necessary cleanup if they were 254 + * interrupted by the panic CPU while printing. 252 255 */ 253 - if (other_cpu_in_panic()) 256 + if (other_cpu_in_panic() && 257 + (!is_reacquire || cur->unsafe_takeover)) { 254 258 return -EPERM; 259 + } 255 260 256 261 if (ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio) 257 262 return -EPERM; ··· 308 301 * Event #1 implies this context is EMERGENCY. 309 302 * Event #2 implies the new context is PANIC. 310 303 * Event #3 occurs when panic() has flushed the console. 311 - * Events #4 and #5 are not possible due to the other_cpu_in_panic() 312 - * check in nbcon_context_try_acquire_direct(). 304 + * Event #4 occurs when a non-panic CPU reacquires. 305 + * Event #5 is not possible due to the other_cpu_in_panic() check 306 + * in nbcon_context_try_acquire_handover(). 313 307 */ 314 308 315 309 return (cur->req_prio == expected_prio); ··· 439 431 WARN_ON_ONCE(ctxt->prio <= cur->prio || ctxt->prio <= cur->req_prio); 440 432 WARN_ON_ONCE(!cur->unsafe); 441 433 434 + /* 435 + * Panic does not imply that the console is owned. However, it 436 + * is critical that non-panic CPUs during panic are unable to 437 + * wait for a handover in order to satisfy the assumptions of 438 + * nbcon_waiter_matches(). In particular, the assumption that 439 + * lower priorities are ignored during panic. 440 + */ 441 + if (other_cpu_in_panic()) 442 + return -EPERM; 443 + 442 444 /* Handover is not possible on the same CPU. */ 443 445 if (cur->cpu == cpu) 444 446 return -EBUSY; ··· 576 558 577 559 /** 578 560 * nbcon_context_try_acquire - Try to acquire nbcon console 579 - * @ctxt: The context of the caller 561 + * @ctxt: The context of the caller 562 + * @is_reacquire: This acquire is a reacquire 580 563 * 581 564 * Context: Under @ctxt->con->device_lock() or local_irq_save(). 582 565 * Return: True if the console was acquired. False otherwise. ··· 587 568 * in an unsafe state. Otherwise, on success the caller may assume 588 569 * the console is not in an unsafe state. 589 570 */ 590 - static bool nbcon_context_try_acquire(struct nbcon_context *ctxt) 571 + static bool nbcon_context_try_acquire(struct nbcon_context *ctxt, bool is_reacquire) 591 572 { 592 573 unsigned int cpu = smp_processor_id(); 593 574 struct console *con = ctxt->console; ··· 596 577 597 578 nbcon_state_read(con, &cur); 598 579 try_again: 599 - err = nbcon_context_try_acquire_direct(ctxt, &cur); 580 + err = nbcon_context_try_acquire_direct(ctxt, &cur, is_reacquire); 600 581 if (err != -EBUSY) 601 582 goto out; 602 583 ··· 932 913 { 933 914 struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); 934 915 935 - while (!nbcon_context_try_acquire(ctxt)) 916 + while (!nbcon_context_try_acquire(ctxt, true)) 936 917 cpu_relax(); 937 918 938 919 nbcon_write_context_set_buf(wctxt, NULL, 0); ··· 1120 1101 cant_migrate(); 1121 1102 } 1122 1103 1123 - if (!nbcon_context_try_acquire(ctxt)) 1104 + if (!nbcon_context_try_acquire(ctxt, false)) 1124 1105 goto out; 1125 1106 1126 1107 /* ··· 1505 1486 ctxt->prio = nbcon_get_default_prio(); 1506 1487 ctxt->allow_unsafe_takeover = allow_unsafe_takeover; 1507 1488 1508 - if (!nbcon_context_try_acquire(ctxt)) 1489 + if (!nbcon_context_try_acquire(ctxt, false)) 1509 1490 return -EPERM; 1510 1491 1511 1492 while (nbcon_seq_read(con) < stop_seq) { ··· 1690 1671 { 1691 1672 struct nbcon_state state = { }; 1692 1673 1674 + /* Synchronize the kthread start. */ 1675 + lockdep_assert_console_list_lock_held(); 1676 + 1693 1677 /* The write_thread() callback is mandatory. */ 1694 1678 if (WARN_ON(!con->write_thread)) 1695 1679 return false; ··· 1723 1701 return false; 1724 1702 } 1725 1703 1726 - if (printk_kthreads_running) { 1704 + if (printk_kthreads_ready && !have_boot_console) { 1727 1705 if (!nbcon_kthread_create(con)) { 1728 1706 kfree(con->pbufs); 1729 1707 con->pbufs = NULL; 1730 1708 return false; 1731 1709 } 1710 + 1711 + /* Might be the first kthread. */ 1712 + printk_kthreads_running = true; 1732 1713 } 1733 1714 } 1734 1715 ··· 1741 1716 /** 1742 1717 * nbcon_free - Free and cleanup the nbcon console specific data 1743 1718 * @con: Console to free/cleanup nbcon data 1719 + * 1720 + * Important: @have_nbcon_console must be updated before calling 1721 + * this function. In particular, it can be set only when there 1722 + * is still another nbcon console registered. 1744 1723 */ 1745 1724 void nbcon_free(struct console *con) 1746 1725 { 1747 1726 struct nbcon_state state = { }; 1748 1727 1749 - if (printk_kthreads_running) 1728 + /* Synchronize the kthread stop. */ 1729 + lockdep_assert_console_list_lock_held(); 1730 + 1731 + if (printk_kthreads_running) { 1750 1732 nbcon_kthread_stop(con); 1733 + 1734 + /* Might be the last nbcon console. 1735 + * 1736 + * Do not rely on printk_kthreads_check_locked(). It is not 1737 + * called in some code paths, see nbcon_free() callers. 1738 + */ 1739 + if (!have_nbcon_console) 1740 + printk_kthreads_running = false; 1741 + } 1751 1742 1752 1743 nbcon_state_set(con, &state); 1753 1744 ··· 1803 1762 ctxt->console = con; 1804 1763 ctxt->prio = NBCON_PRIO_NORMAL; 1805 1764 1806 - if (!nbcon_context_try_acquire(ctxt)) 1765 + if (!nbcon_context_try_acquire(ctxt, false)) 1807 1766 return false; 1808 1767 1809 1768 if (!nbcon_context_enter_unsafe(ctxt))
+11 -9
kernel/printk/printk.c
··· 3574 3574 static int unregister_console_locked(struct console *console); 3575 3575 3576 3576 /* True when system boot is far enough to create printer threads. */ 3577 - static bool printk_kthreads_ready __ro_after_init; 3577 + bool printk_kthreads_ready __ro_after_init; 3578 3578 3579 3579 static struct task_struct *printk_legacy_kthread; 3580 3580 ··· 3713 3713 if (!printk_kthreads_ready) 3714 3714 return; 3715 3715 3716 + /* Start or stop the legacy kthread when needed. */ 3716 3717 if (have_legacy_console || have_boot_console) { 3717 3718 if (!printk_legacy_kthread && 3718 3719 force_legacy_kthread() && ··· 4205 4204 */ 4206 4205 synchronize_srcu(&console_srcu); 4207 4206 4208 - if (console->flags & CON_NBCON) 4209 - nbcon_free(console); 4210 - 4211 - console_sysfs_notify(); 4212 - 4213 - if (console->exit) 4214 - res = console->exit(console); 4215 - 4216 4207 /* 4217 4208 * With this console gone, the global flags tracking registered 4218 4209 * console types may have changed. Update them. ··· 4224 4231 have_legacy_console = found_legacy_con; 4225 4232 if (!found_nbcon_con) 4226 4233 have_nbcon_console = found_nbcon_con; 4234 + 4235 + /* @have_nbcon_console must be updated before calling nbcon_free(). */ 4236 + if (console->flags & CON_NBCON) 4237 + nbcon_free(console); 4238 + 4239 + console_sysfs_notify(); 4240 + 4241 + if (console->exit) 4242 + res = console->exit(console); 4227 4243 4228 4244 /* Changed console list, may require printer threads to start/stop. */ 4229 4245 printk_kthreads_check_locked();
+61 -9
lib/vsprintf.c
··· 60 60 bool no_hash_pointers __ro_after_init; 61 61 EXPORT_SYMBOL_GPL(no_hash_pointers); 62 62 63 + /* 64 + * Hashed pointers policy selected by "hash_pointers=..." boot param 65 + * 66 + * `auto` - Hashed pointers enabled unless disabled by slub_debug_enabled=true 67 + * `always` - Hashed pointers enabled unconditionally 68 + * `never` - Hashed pointers disabled unconditionally 69 + */ 70 + enum hash_pointers_policy { 71 + HASH_PTR_AUTO = 0, 72 + HASH_PTR_ALWAYS, 73 + HASH_PTR_NEVER 74 + }; 75 + static enum hash_pointers_policy hash_pointers_mode __initdata; 76 + 63 77 noinline 64 78 static unsigned long long simple_strntoull(const char *startp, char **endp, unsigned int base, size_t max_chars) 65 79 { ··· 1713 1699 return buf; 1714 1700 } 1715 1701 1716 - #pragma GCC diagnostic push 1717 - #ifndef __clang__ 1718 - #pragma GCC diagnostic ignored "-Wsuggest-attribute=format" 1719 - #endif 1702 + __diag_push(); 1703 + __diag_ignore(GCC, all, "-Wsuggest-attribute=format", 1704 + "Not a valid __printf() conversion candidate."); 1720 1705 static char *va_format(char *buf, char *end, struct va_format *va_fmt, 1721 1706 struct printf_spec spec) 1722 1707 { ··· 1730 1717 1731 1718 return buf; 1732 1719 } 1733 - #pragma GCC diagnostic pop 1720 + __diag_pop(); 1734 1721 1735 1722 static noinline_for_stack 1736 1723 char *uuid_string(char *buf, char *end, const u8 *addr, ··· 2302 2289 return resource_string(buf, end, ptr, spec, fmt); 2303 2290 } 2304 2291 2305 - int __init no_hash_pointers_enable(char *str) 2292 + void __init hash_pointers_finalize(bool slub_debug) 2306 2293 { 2307 - if (no_hash_pointers) 2308 - return 0; 2294 + switch (hash_pointers_mode) { 2295 + case HASH_PTR_ALWAYS: 2296 + no_hash_pointers = false; 2297 + break; 2298 + case HASH_PTR_NEVER: 2299 + no_hash_pointers = true; 2300 + break; 2301 + case HASH_PTR_AUTO: 2302 + default: 2303 + no_hash_pointers = slub_debug; 2304 + break; 2305 + } 2309 2306 2310 - no_hash_pointers = true; 2307 + if (!no_hash_pointers) 2308 + return; 2311 2309 2312 2310 pr_warn("**********************************************************\n"); 2313 2311 pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n"); ··· 2331 2307 pr_warn("** the kernel, report this immediately to your system **\n"); 2332 2308 pr_warn("** administrator! **\n"); 2333 2309 pr_warn("** **\n"); 2310 + pr_warn("** Use hash_pointers=always to force this mode off **\n"); 2311 + pr_warn("** **\n"); 2334 2312 pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n"); 2335 2313 pr_warn("**********************************************************\n"); 2314 + } 2315 + 2316 + static int __init hash_pointers_mode_parse(char *str) 2317 + { 2318 + if (!str) { 2319 + pr_warn("Hash pointers mode empty; falling back to auto.\n"); 2320 + hash_pointers_mode = HASH_PTR_AUTO; 2321 + } else if (strncmp(str, "auto", 4) == 0) { 2322 + pr_info("Hash pointers mode set to auto.\n"); 2323 + hash_pointers_mode = HASH_PTR_AUTO; 2324 + } else if (strncmp(str, "never", 5) == 0) { 2325 + pr_info("Hash pointers mode set to never.\n"); 2326 + hash_pointers_mode = HASH_PTR_NEVER; 2327 + } else if (strncmp(str, "always", 6) == 0) { 2328 + pr_info("Hash pointers mode set to always.\n"); 2329 + hash_pointers_mode = HASH_PTR_ALWAYS; 2330 + } else { 2331 + pr_warn("Unknown hash_pointers mode '%s' specified; assuming auto.\n", str); 2332 + hash_pointers_mode = HASH_PTR_AUTO; 2333 + } 2336 2334 2337 2335 return 0; 2336 + } 2337 + early_param("hash_pointers", hash_pointers_mode_parse); 2338 + 2339 + static int __init no_hash_pointers_enable(char *str) 2340 + { 2341 + return hash_pointers_mode_parse("never"); 2338 2342 } 2339 2343 early_param("no_hash_pointers", no_hash_pointers_enable); 2340 2344
+2 -3
mm/slub.c
··· 6312 6312 if (debug_guardpage_minorder()) 6313 6313 slub_max_order = 0; 6314 6314 6315 - /* Print slub debugging pointers without hashing */ 6316 - if (__slub_debug_enabled()) 6317 - no_hash_pointers_enable(NULL); 6315 + /* Inform pointer hashing choice about slub debugging state. */ 6316 + hash_pointers_finalize(__slub_debug_enabled()); 6318 6317 6319 6318 kmem_cache_node = &boot_kmem_cache_node; 6320 6319 kmem_cache = &boot_kmem_cache;