5188 lines · 134.4 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* *  linux/kernel/printk.c * *  Copyright (C) 1991, 1992  Linus Torvalds * * Modified to make sys_syslog() more flexible: added commands to * return the last 4k of kernel messages, regardless of whether * they've been read or not.  Added option to suppress kernel printk's * to the console.  Added hook for sending the console messages * elsewhere, in preparation for a serial line console (someday). * Ted Ts'o, 2/11/93. * Modified for sysctl support, 1/8/97, Chris Horn. * Fixed SMP synchronization, 08/08/99, Manfred Spraul *     manfred@colorfullife.com * Rewrote bits to get rid of console_lock *	01Mar01 Andrew Morton */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/kernel.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/tty_driver.h>#include <linux/console.h>#include <linux/init.h>#include <linux/jiffies.h>#include <linux/nmi.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/delay.h>#include <linux/smp.h>#include <linux/security.h>#include <linux/memblock.h>#include <linux/syscalls.h>#include <linux/syscore_ops.h>#include <linux/vmcore_info.h>#include <linux/ratelimit.h>#include <linux/kmsg_dump.h>#include <linux/syslog.h>#include <linux/cpu.h>#include <linux/rculist.h>#include <linux/poll.h>#include <linux/irq_work.h>#include <linux/ctype.h>#include <linux/uio.h>#include <linux/sched/clock.h>#include <linux/sched/debug.h>#include <linux/sched/task_stack.h>#include <linux/panic.h> #include <linux/uaccess.h>#include <asm/sections.h> #include <trace/events/initcall.h>#define CREATE_TRACE_POINTS#include <trace/events/printk.h> #include "printk_ringbuffer.h"#include "console_cmdline.h"#include "braille.h"#include "internal.h" int console_printk[4] = {	CONSOLE_LOGLEVEL_DEFAULT,	/* console_loglevel */	MESSAGE_LOGLEVEL_DEFAULT,	/* default_message_loglevel */	CONSOLE_LOGLEVEL_MIN,		/* minimum_console_loglevel */	CONSOLE_LOGLEVEL_DEFAULT,	/* default_console_loglevel */};EXPORT_SYMBOL_GPL(console_printk); atomic_t ignore_console_lock_warning __read_mostly = ATOMIC_INIT(0);EXPORT_SYMBOL(ignore_console_lock_warning); EXPORT_TRACEPOINT_SYMBOL_GPL(console); /* * Low level drivers may need that to know if they can schedule in * their unblank() callback or not. So let's export it. */int oops_in_progress;EXPORT_SYMBOL(oops_in_progress); /* * console_mutex protects console_list updates and console->flags updates. * The flags are synchronized only for consoles that are registered, i.e. * accessible via the console list. */static DEFINE_MUTEX(console_mutex); /* * console_sem protects updates to console->seq * and also provides serialization for console printing. */static DEFINE_SEMAPHORE(console_sem, 1);HLIST_HEAD(console_list);EXPORT_SYMBOL_GPL(console_list);DEFINE_STATIC_SRCU(console_srcu); /* * System may need to suppress printk message under certain * circumstances, like after kernel panic happens. */int __read_mostly suppress_printk; #ifdef CONFIG_LOCKDEPstatic struct lockdep_map console_lock_dep_map = {	.name = "console_lock"}; void lockdep_assert_console_list_lock_held(void){	lockdep_assert_held(&console_mutex);}EXPORT_SYMBOL(lockdep_assert_console_list_lock_held);#endif #ifdef CONFIG_DEBUG_LOCK_ALLOCbool console_srcu_read_lock_is_held(void){	return srcu_read_lock_held(&console_srcu);}EXPORT_SYMBOL(console_srcu_read_lock_is_held);#endif enum devkmsg_log_bits {	__DEVKMSG_LOG_BIT_ON = 0,	__DEVKMSG_LOG_BIT_OFF,	__DEVKMSG_LOG_BIT_LOCK,}; enum devkmsg_log_masks {	DEVKMSG_LOG_MASK_ON             = BIT(__DEVKMSG_LOG_BIT_ON),	DEVKMSG_LOG_MASK_OFF            = BIT(__DEVKMSG_LOG_BIT_OFF),	DEVKMSG_LOG_MASK_LOCK           = BIT(__DEVKMSG_LOG_BIT_LOCK),}; /* Keep both the 'on' and 'off' bits clear, i.e. ratelimit by default: */#define DEVKMSG_LOG_MASK_DEFAULT	0 static unsigned int __read_mostly devkmsg_log = DEVKMSG_LOG_MASK_DEFAULT; static int __control_devkmsg(char *str){	size_t len; 	if (!str)		return -EINVAL; 	len = str_has_prefix(str, "on");	if (len) {		devkmsg_log = DEVKMSG_LOG_MASK_ON;		return len;	} 	len = str_has_prefix(str, "off");	if (len) {		devkmsg_log = DEVKMSG_LOG_MASK_OFF;		return len;	} 	len = str_has_prefix(str, "ratelimit");	if (len) {		devkmsg_log = DEVKMSG_LOG_MASK_DEFAULT;		return len;	} 	return -EINVAL;} static int __init control_devkmsg(char *str){	if (__control_devkmsg(str) < 0) {		pr_warn("printk.devkmsg: bad option string '%s'\n", str);		return 1;	} 	/*	 * Set sysctl string accordingly:	 */	if (devkmsg_log == DEVKMSG_LOG_MASK_ON)		strscpy(devkmsg_log_str, "on");	else if (devkmsg_log == DEVKMSG_LOG_MASK_OFF)		strscpy(devkmsg_log_str, "off");	/* else "ratelimit" which is set by default. */ 	/*	 * Sysctl cannot change it anymore. The kernel command line setting of	 * this parameter is to force the setting to be permanent throughout the	 * runtime of the system. This is a precautionary measure against userspace	 * trying to be a smarta** and attempting to change it up on us.	 */	devkmsg_log |= DEVKMSG_LOG_MASK_LOCK; 	return 1;}__setup("printk.devkmsg=", control_devkmsg); char devkmsg_log_str[DEVKMSG_STR_MAX_SIZE] = "ratelimit";#if defined(CONFIG_PRINTK) && defined(CONFIG_SYSCTL)int devkmsg_sysctl_set_loglvl(const struct ctl_table *table, int write,			      void *buffer, size_t *lenp, loff_t *ppos){	char old_str[DEVKMSG_STR_MAX_SIZE];	unsigned int old;	int err; 	if (write) {		if (devkmsg_log & DEVKMSG_LOG_MASK_LOCK)			return -EINVAL; 		old = devkmsg_log;		strscpy(old_str, devkmsg_log_str);	} 	err = proc_dostring(table, write, buffer, lenp, ppos);	if (err)		return err; 	if (write) {		err = __control_devkmsg(devkmsg_log_str); 		/*		 * Do not accept an unknown string OR a known string with		 * trailing crap...		 */		if (err < 0 || (err + 1 != *lenp)) { 			/* ... and restore old setting. */			devkmsg_log = old;			strscpy(devkmsg_log_str, old_str); 			return -EINVAL;		}	} 	return 0;}#endif /* CONFIG_PRINTK && CONFIG_SYSCTL */ /** * console_list_lock - Lock the console list * * For console list or console->flags updates */void console_list_lock(void)	__acquires(&console_mutex){	/*	 * In unregister_console() and console_force_preferred_locked(),	 * synchronize_srcu() is called with the console_list_lock held.	 * Therefore it is not allowed that the console_list_lock is taken	 * with the srcu_lock held.	 *	 * Detecting if this context is really in the read-side critical	 * section is only possible if the appropriate debug options are	 * enabled.	 */	WARN_ON_ONCE(debug_lockdep_rcu_enabled() &&		     srcu_read_lock_held(&console_srcu)); 	mutex_lock(&console_mutex);}EXPORT_SYMBOL(console_list_lock); /** * console_list_unlock - Unlock the console list * * Counterpart to console_list_lock() */void console_list_unlock(void)	__releases(&console_mutex){	mutex_unlock(&console_mutex);}EXPORT_SYMBOL(console_list_unlock); /** * console_srcu_read_lock - Register a new reader for the *	SRCU-protected console list * * Use for_each_console_srcu() to iterate the console list * * Context: Any context. * Return: A cookie to pass to console_srcu_read_unlock(). */int console_srcu_read_lock(void)	__acquires(&console_srcu){	return srcu_read_lock_nmisafe(&console_srcu);}EXPORT_SYMBOL(console_srcu_read_lock); /** * console_srcu_read_unlock - Unregister an old reader from *	the SRCU-protected console list * @cookie: cookie returned from console_srcu_read_lock() * * Counterpart to console_srcu_read_lock() */void console_srcu_read_unlock(int cookie)	__releases(&console_srcu){	srcu_read_unlock_nmisafe(&console_srcu, cookie);}EXPORT_SYMBOL(console_srcu_read_unlock); /* * Helper macros to handle lockdep when locking/unlocking console_sem. We use * macros instead of functions so that _RET_IP_ contains useful information. */#define down_console_sem() do { \	down(&console_sem);\	mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_);\} while (0) static int __down_trylock_console_sem(unsigned long ip){	int lock_failed;	unsigned long flags; 	/*	 * Here and in __up_console_sem() we need to be in safe mode,	 * because spindump/WARN/etc from under console ->lock will	 * deadlock in printk()->down_trylock_console_sem() otherwise.	 */	printk_safe_enter_irqsave(flags);	lock_failed = down_trylock(&console_sem);	printk_safe_exit_irqrestore(flags); 	if (lock_failed)		return 1;	mutex_acquire(&console_lock_dep_map, 0, 1, ip);	return 0;}#define down_trylock_console_sem() __down_trylock_console_sem(_RET_IP_) static void __up_console_sem(unsigned long ip){	unsigned long flags; 	mutex_release(&console_lock_dep_map, ip); 	printk_safe_enter_irqsave(flags);	up(&console_sem);	printk_safe_exit_irqrestore(flags);}#define up_console_sem() __up_console_sem(_RET_IP_) /* * This is used for debugging the mess that is the VT code by * keeping track if we have the console semaphore held. It's * definitely not the perfect debug tool (we don't know if _WE_ * hold it and are racing, but it helps tracking those weird code * paths in the console code where we end up in places I want * locked without the console semaphore held). */static int console_locked; /* *	Array of consoles built from command line options (console=) */ #define MAX_CMDLINECONSOLES 8 static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES]; static int preferred_console = -1;int console_set_on_cmdline;EXPORT_SYMBOL(console_set_on_cmdline); /* Flag: console code may call schedule() */static int console_may_schedule; enum con_msg_format_flags {	MSG_FORMAT_DEFAULT	= 0,	MSG_FORMAT_SYSLOG	= (1 << 0),}; static int console_msg_format = MSG_FORMAT_DEFAULT; /* * The printk log buffer consists of a sequenced collection of records, each * containing variable length message text. Every record also contains its * own meta-data (@info). * * Every record meta-data carries the timestamp in microseconds, as well as * the standard userspace syslog level and syslog facility. The usual kernel * messages use LOG_KERN; userspace-injected messages always carry a matching * syslog facility, by default LOG_USER. The origin of every message can be * reliably determined that way. * * The human readable log message of a record is available in @text, the * length of the message text in @text_len. The stored message is not * terminated. * * Optionally, a record can carry a dictionary of properties (key/value * pairs), to provide userspace with a machine-readable message context. * * Examples for well-defined, commonly used property names are: *   DEVICE=b12:8               device identifier *                                b12:8         block dev_t *                                c127:3        char dev_t *                                n8            netdev ifindex *                                +sound:card0  subsystem:devname *   SUBSYSTEM=pci              driver-core subsystem name * * Valid characters in property names are [a-zA-Z0-9.-_]. Property names * and values are terminated by a '\0' character. * * Example of record values: *   record.text_buf                = "it's a line" (unterminated) *   record.info.seq                = 56 *   record.info.ts_nsec            = 36863 *   record.info.text_len           = 11 *   record.info.facility           = 0 (LOG_KERN) *   record.info.flags              = 0 *   record.info.level              = 3 (LOG_ERR) *   record.info.caller_id          = 299 (task 299) *   record.info.dev_info.subsystem = "pci" (terminated) *   record.info.dev_info.device    = "+pci:0000:00:01.0" (terminated) * * The 'struct printk_info' buffer must never be directly exported to * userspace, it is a kernel-private implementation detail that might * need to be changed in the future, when the requirements change. * * /dev/kmsg exports the structured data in the following line format: *   "<level>,<sequnum>,<timestamp>,<contflag>[,additional_values, ... ];<message text>\n" * * Users of the export format should ignore possible additional values * separated by ',', and find the message after the ';' character. * * The optional key/value pairs are attached as continuation lines starting * with a space character and terminated by a newline. All possible * non-prinatable characters are escaped in the "\xff" notation. */ /* syslog_lock protects syslog_* variables and write access to clear_seq. */static DEFINE_MUTEX(syslog_lock); /* * Specifies if a legacy console is registered. If legacy consoles are * present, it is necessary to perform the console lock/unlock dance * whenever console flushing should occur. */bool have_legacy_console; /* * Specifies if an nbcon console is registered. If nbcon consoles are present, * synchronous printing of legacy consoles will not occur during panic until * the backtrace has been stored to the ringbuffer. */bool have_nbcon_console; /* * Specifies if a boot console is registered. If boot consoles are present, * nbcon consoles cannot print simultaneously and must be synchronized by * the console lock. This is because boot consoles and nbcon consoles may * have mapped the same hardware. */bool have_boot_console; /* See printk_legacy_allow_panic_sync() for details. */bool legacy_allow_panic_sync; /* Avoid using irq_work when suspending. */bool console_irqwork_blocked; #ifdef CONFIG_PRINTKDECLARE_WAIT_QUEUE_HEAD(log_wait);static DECLARE_WAIT_QUEUE_HEAD(legacy_wait);/* All 3 protected by @syslog_lock. *//* the next printk record to read by syslog(READ) or /proc/kmsg */static u64 syslog_seq;static size_t syslog_partial;static bool syslog_time; /* True when _all_ printer threads are available for printing. */bool printk_kthreads_running; struct latched_seq {	seqcount_latch_t	latch;	u64			val[2];}; /* * The next printk record to read after the last 'clear' command. There are * two copies (updated with seqcount_latch) so that reads can locklessly * access a valid value. Writers are synchronized by @syslog_lock. */static struct latched_seq clear_seq = {	.latch		= SEQCNT_LATCH_ZERO(clear_seq.latch),	.val[0]		= 0,	.val[1]		= 0,}; #define LOG_LEVEL(v)		((v) & 0x07)#define LOG_FACILITY(v)		((v) >> 3 & 0xff) 

Lines 1–500 of 5188.