From: Borislav Petkov <[email protected]> Add a "printk.kmsg" kernel command line parameter which controls how userspace writes into /dev/kmsg. It has two options:
* on - unlimited logging from userspace * off - logging from userspace gets ignored The default setting is to ratelimit the messages written to it. It additionally does not limit logging to /dev/kmsg while the system is booting if we haven't disabled it on the command line. This patch is based on previous patches from Linus and Steven. Signed-off-by: Borislav Petkov <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Steven Rostedt <[email protected]> --- Documentation/kernel-parameters.txt | 6 ++++ kernel/printk/printk.c | 57 +++++++++++++++++++++++++++++++------ 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 82b42c958d1c..4799c88b7258 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -3150,6 +3150,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Format: <bool> (1/Y/y=enable, 0/N/n=disable) default: disabled + printk.kmsg={on,off} + Control writing to /dev/kmsg. + on - unlimited logging to /dev/kmsg from userspace + off - logging to /dev/kmsg disabled + Default: ratelimited logging. + printk.time= Show timing data prefixed to each printk message line Format: <bool> (1/Y/y=enable, 0/N/n=disable) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 60cdf6386763..33701a166f26 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -86,6 +86,29 @@ static struct lockdep_map console_lock_dep_map = { }; #endif +#define DEVKMSG_LOG_RATELIMIT 0 +#define DEVKMSG_LOG_ON 1 +#define DEVKMSG_LOG_OFF 2 + +/* DEVKMSG_LOG_RATELIMIT by default */ +static unsigned int __read_mostly devkmsg_log; +static int __init control_devkmsg(char *str) +{ + if (!str) + return -EINVAL; + + if (!strncmp(str, "on", 2)) + devkmsg_log = DEVKMSG_LOG_ON; + else if (!strncmp(str, "off", 3)) + devkmsg_log = DEVKMSG_LOG_OFF; + else + return -EINVAL; + + return 0; +} +__setup("printk.kmsg=", control_devkmsg); + + /* * Number of registered extended console drivers. * @@ -614,6 +637,7 @@ struct devkmsg_user { u64 seq; u32 idx; enum log_flags prev; + struct ratelimit_state rs; struct mutex lock; char buf[CONSOLE_EXT_LOG_MAX]; }; @@ -623,11 +647,24 @@ static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from) char *buf, *line; int level = default_message_loglevel; int facility = 1; /* LOG_USER */ + struct file *file = iocb->ki_filp; + struct devkmsg_user *user = file->private_data; size_t len = iov_iter_count(from); ssize_t ret = len; - if (len > LOG_LINE_MAX) + if (!user || len > LOG_LINE_MAX) return -EINVAL; + + /* Ignore when user logging is disabled. */ + if (devkmsg_log == DEVKMSG_LOG_OFF) + return len; + + /* Ratelimit when not explicitly enabled or when we're not booting. */ + if ((system_state != SYSTEM_BOOTING) && (devkmsg_log != DEVKMSG_LOG_ON)) { + if (!___ratelimit(&user->rs, current->comm)) + return ret; + } + buf = kmalloc(len+1, GFP_KERNEL); if (buf == NULL) return -ENOMEM; @@ -801,18 +838,20 @@ static int devkmsg_open(struct inode *inode, struct file *file) int err; /* write-only does not need any file context */ - if ((file->f_flags & O_ACCMODE) == O_WRONLY) - return 0; - - err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL, - SYSLOG_FROM_READER); - if (err) - return err; + if ((file->f_flags & O_ACCMODE) != O_WRONLY) { + err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL, + SYSLOG_FROM_READER); + if (err) + return err; + } user = kmalloc(sizeof(struct devkmsg_user), GFP_KERNEL); if (!user) return -ENOMEM; + ratelimit_default_init(&user->rs); + ratelimit_set_flags(&user->rs, RATELIMIT_MSG_ON_RELEASE); + mutex_init(&user->lock); raw_spin_lock_irq(&logbuf_lock); @@ -831,6 +870,8 @@ static int devkmsg_release(struct inode *inode, struct file *file) if (!user) return 0; + ratelimit_state_exit(&user->rs); + mutex_destroy(&user->lock); kfree(user); return 0; -- 2.7.3

