2820 lines · 69.8 KB · C
RawDownload
/* *  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 */ #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/interrupt.h>			/* For in_interrupt() */#include <linux/delay.h>#include <linux/smp.h>#include <linux/security.h>#include <linux/bootmem.h>#include <linux/memblock.h>#include <linux/syscalls.h>#include <linux/kexec.h>#include <linux/kdb.h>#include <linux/ratelimit.h>#include <linux/kmsg_dump.h>#include <linux/syslog.h>#include <linux/cpu.h>#include <linux/notifier.h>#include <linux/rculist.h>#include <linux/poll.h> #include <asm/uaccess.h> #define CREATE_TRACE_POINTS#include <trace/events/printk.h> /* * Architectures can override it: */void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...){} /* printk's without a loglevel use this.. */#define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL /* We show everything that is MORE important than this.. */#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */ DECLARE_WAIT_QUEUE_HEAD(log_wait); int console_printk[4] = {	DEFAULT_CONSOLE_LOGLEVEL,	/* console_loglevel */	DEFAULT_MESSAGE_LOGLEVEL,	/* default_message_loglevel */	MINIMUM_CONSOLE_LOGLEVEL,	/* minimum_console_loglevel */	DEFAULT_CONSOLE_LOGLEVEL,	/* default_console_loglevel */}; /* * 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_sem protects the console_drivers list, and also * provides serialisation for access to the entire console * driver system. */static DEFINE_SEMAPHORE(console_sem);struct console *console_drivers;EXPORT_SYMBOL_GPL(console_drivers); /* * 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 are racing, but it helps tracking those weird code * path in the console code where we end up in places I want * locked without the console sempahore held */static int console_locked, console_suspended; /* * If exclusive_console is non-NULL then only this console is to be printed to. */static struct console *exclusive_console; /* *	Array of consoles built from command line options (console=) */struct console_cmdline{	char	name[8];			/* Name of the driver	    */	int	index;				/* Minor dev. to use	    */	char	*options;			/* Options for the driver   */#ifdef CONFIG_A11Y_BRAILLE_CONSOLE	char	*brl_options;			/* Options for braille driver */#endif}; #define MAX_CMDLINECONSOLES 8 static struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];static int selected_console = -1;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; /* * The printk log buffer consists of a chain of concatenated variable * length records. Every record starts with a record header, containing * the overall length of the record. * * The heads to the first and last entry in the buffer, as well as the * sequence numbers of these both entries are maintained when messages * are stored.. * * If the heads indicate available messages, the length in the header * tells the start next message. A length == 0 for the next message * indicates a wrap-around to the beginning of the buffer. * * Every record carries the monotonic 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 directly follows the message header. The * length of the message text is stored in the header, the stored message * is not terminated. * * Optionally, a message 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.-_]. The plain text value * follows directly after a '=' character. Every property is terminated by * a '\0' character. The last property is not terminated. * * Example of a message structure: *   0000  ff 8f 00 00 00 00 00 00      monotonic time in nsec *   0008  34 00                        record is 52 bytes long *   000a        0b 00                  text is 11 bytes long *   000c              1f 00            dictionary is 23 bytes long *   000e                    03 00      LOG_KERN (facility) LOG_ERR (level) *   0010  69 74 27 73 20 61 20 6c      "it's a l" *         69 6e 65                     "ine" *   001b           44 45 56 49 43      "DEVIC" *         45 3d 62 38 3a 32 00 44      "E=b8:2\0D" *         52 49 56 45 52 3d 62 75      "RIVER=bu" *         67                           "g" *   0032     00 00 00                  padding to next message header * * The 'struct log' buffer header 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;<message text>\n" * * 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. * * Users of the export format should ignore possible additional values * separated by ',', and find the message after the ';' character. */ enum log_flags {	LOG_NOCONS	= 1,	/* already flushed, do not print to console */	LOG_NEWLINE	= 2,	/* text ended with a newline */	LOG_PREFIX	= 4,	/* text started with a prefix */	LOG_CONT	= 8,	/* text is a fragment of a continuation line */}; struct log {	u64 ts_nsec;		/* timestamp in nanoseconds */	u16 len;		/* length of entire record */	u16 text_len;		/* length of text buffer */	u16 dict_len;		/* length of dictionary buffer */	u8 facility;		/* syslog facility */	u8 flags:5;		/* internal record flags */	u8 level:3;		/* syslog level */}; /* * The logbuf_lock protects kmsg buffer, indices, counters. It is also * used in interesting ways to provide interlocking in console_unlock(); */static DEFINE_RAW_SPINLOCK(logbuf_lock); #ifdef CONFIG_PRINTK/* the next printk record to read by syslog(READ) or /proc/kmsg */static u64 syslog_seq;static u32 syslog_idx;static enum log_flags syslog_prev;static size_t syslog_partial; /* index and sequence number of the first record stored in the buffer */static u64 log_first_seq;static u32 log_first_idx; /* index and sequence number of the next record to store in the buffer */static u64 log_next_seq;static u32 log_next_idx; /* the next printk record to write to the console */static u64 console_seq;static u32 console_idx;static enum log_flags console_prev; /* the next printk record to read after the last 'clear' command */static u64 clear_seq;static u32 clear_idx; #define PREFIX_MAX		32#define LOG_LINE_MAX		1024 - PREFIX_MAX /* record buffer */#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)#define LOG_ALIGN 4#else#define LOG_ALIGN __alignof__(struct log)#endif#define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);static char *log_buf = __log_buf;static u32 log_buf_len = __LOG_BUF_LEN; /* cpu currently holding logbuf_lock */static volatile unsigned int logbuf_cpu = UINT_MAX; /* human readable text of the record */static char *log_text(const struct log *msg){	return (char *)msg + sizeof(struct log);} /* optional key/value pair dictionary attached to the record */static char *log_dict(const struct log *msg){	return (char *)msg + sizeof(struct log) + msg->text_len;} /* get record by index; idx must point to valid msg */static struct log *log_from_idx(u32 idx){	struct log *msg = (struct log *)(log_buf + idx); 	/*	 * A length == 0 record is the end of buffer marker. Wrap around and	 * read the message at the start of the buffer.	 */	if (!msg->len)		return (struct log *)log_buf;	return msg;} /* get next record; idx must point to valid msg */static u32 log_next(u32 idx){	struct log *msg = (struct log *)(log_buf + idx); 	/* length == 0 indicates the end of the buffer; wrap */	/*	 * A length == 0 record is the end of buffer marker. Wrap around and	 * read the message at the start of the buffer as *this* one, and	 * return the one after that.	 */	if (!msg->len) {		msg = (struct log *)log_buf;		return msg->len;	}	return idx + msg->len;} /* insert record into the buffer, discard old ones, update heads */static void log_store(int facility, int level,		      enum log_flags flags, u64 ts_nsec,		      const char *dict, u16 dict_len,		      const char *text, u16 text_len){	struct log *msg;	u32 size, pad_len; 	/* number of '\0' padding bytes to next message */	size = sizeof(struct log) + text_len + dict_len;	pad_len = (-size) & (LOG_ALIGN - 1);	size += pad_len; 	while (log_first_seq < log_next_seq) {		u32 free; 		if (log_next_idx > log_first_idx)			free = max(log_buf_len - log_next_idx, log_first_idx);		else			free = log_first_idx - log_next_idx; 		if (free > size + sizeof(struct log))			break; 		/* drop old messages until we have enough contiuous space */		log_first_idx = log_next(log_first_idx);		log_first_seq++;	} 	if (log_next_idx + size + sizeof(struct log) >= log_buf_len) {		/*		 * This message + an additional empty header does not fit		 * at the end of the buffer. Add an empty header with len == 0		 * to signify a wrap around.		 */		memset(log_buf + log_next_idx, 0, sizeof(struct log));		log_next_idx = 0;	} 	/* fill message */	msg = (struct log *)(log_buf + log_next_idx);	memcpy(log_text(msg), text, text_len);	msg->text_len = text_len;	memcpy(log_dict(msg), dict, dict_len);	msg->dict_len = dict_len;	msg->facility = facility;	msg->level = level & 7;	msg->flags = flags & 0x1f;	if (ts_nsec > 0)		msg->ts_nsec = ts_nsec;	else		msg->ts_nsec = local_clock();	memset(log_dict(msg) + dict_len, 0, pad_len);	msg->len = sizeof(struct log) + text_len + dict_len + pad_len; 	/* insert message */	log_next_idx += msg->len;	log_next_seq++;} /* /dev/kmsg - userspace message inject/listen interface */struct devkmsg_user {	u64 seq;	u32 idx;	enum log_flags prev;	struct mutex lock;	char buf[8192];}; static ssize_t devkmsg_writev(struct kiocb *iocb, const struct iovec *iv,			      unsigned long count, loff_t pos){	char *buf, *line;	int i;	int level = default_message_loglevel;	int facility = 1;	/* LOG_USER */	size_t len = iov_length(iv, count);	ssize_t ret = len; 	if (len > LOG_LINE_MAX)		return -EINVAL;	buf = kmalloc(len+1, GFP_KERNEL);	if (buf == NULL)		return -ENOMEM; 	line = buf;	for (i = 0; i < count; i++) {		if (copy_from_user(line, iv[i].iov_base, iv[i].iov_len)) {			ret = -EFAULT;			goto out;		}		line += iv[i].iov_len;	} 	/*	 * Extract and skip the syslog prefix <[0-9]*>. Coming from userspace	 * the decimal value represents 32bit, the lower 3 bit are the log	 * level, the rest are the log facility.	 *	 * If no prefix or no userspace facility is specified, we	 * enforce LOG_USER, to be able to reliably distinguish	 * kernel-generated messages from userspace-injected ones.	 */	line = buf;	if (line[0] == '<') {		char *endp = NULL; 		i = simple_strtoul(line+1, &endp, 10);		if (endp && endp[0] == '>') {			level = i & 7;			if (i >> 3)				facility = i >> 3;			endp++;			len -= endp - line;			line = endp;		}	}	line[len] = '\0'; 	printk_emit(facility, level, NULL, 0, "%s", line);out:	kfree(buf);	return ret;} static ssize_t devkmsg_read(struct file *file, char __user *buf,			    size_t count, loff_t *ppos){	struct devkmsg_user *user = file->private_data;	struct log *msg;	u64 ts_usec;	size_t i;	char cont = '-';	size_t len;	ssize_t ret; 	if (!user)		return -EBADF; 	ret = mutex_lock_interruptible(&user->lock);	if (ret)		return ret;	raw_spin_lock_irq(&logbuf_lock);	while (user->seq == log_next_seq) {		if (file->f_flags & O_NONBLOCK) {			ret = -EAGAIN;			raw_spin_unlock_irq(&logbuf_lock);			goto out;		} 		raw_spin_unlock_irq(&logbuf_lock);		ret = wait_event_interruptible(log_wait,					       user->seq != log_next_seq);		if (ret)			goto out;		raw_spin_lock_irq(&logbuf_lock);	} 	if (user->seq < log_first_seq) {		/* our last seen message is gone, return error and reset */		user->idx = log_first_idx;		user->seq = log_first_seq;		ret = -EPIPE;		raw_spin_unlock_irq(&logbuf_lock);		goto out;	} 	msg = log_from_idx(user->idx);	ts_usec = msg->ts_nsec;	do_div(ts_usec, 1000); 	/*	 * If we couldn't merge continuation line fragments during the print,	 * export the stored flags to allow an optional external merge of the	 * records. Merging the records isn't always neccessarily correct, like	 * when we hit a race during printing. In most cases though, it produces	 * better readable output. 'c' in the record flags mark the first	 * fragment of a line, '+' the following.	 */	if (msg->flags & LOG_CONT && !(user->prev & LOG_CONT))		cont = 'c';	else if ((msg->flags & LOG_CONT) ||		 ((user->prev & LOG_CONT) && !(msg->flags & LOG_PREFIX)))		cont = '+'; 	len = sprintf(user->buf, "%u,%llu,%llu,%c;",		      (msg->facility << 3) | msg->level,		      user->seq, ts_usec, cont);	user->prev = msg->flags; 	/* escape non-printable characters */	for (i = 0; i < msg->text_len; i++) {		unsigned char c = log_text(msg)[i]; 		if (c < ' ' || c >= 127 || c == '\\')			len += sprintf(user->buf + len, "\\x%02x", c);

Lines 1–500 of 2820.