/* * 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 <linux/irq_work.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 */ 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); #ifdef CONFIG_LOCKDEPstatic struct lockdep_map console_lock_dep_map = { .name = "console_lock"};#endif /* * 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_PRINTKDECLARE_WAIT_QUEUE_HEAD(log_wait);/* 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; Lines 1–500 of 2835. Load more
/* * 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 <linux/irq_work.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 */ 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); #ifdef CONFIG_LOCKDEP static struct lockdep_map console_lock_dep_map = { .name = "console_lock" }; #endif /* * 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 DECLARE_WAIT_QUEUE_HEAD(log_wait); /* 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;