* [PATCH 0/2] printk.kmsg: Ratelimit it by default @ 2016-06-14 10:12 Borislav Petkov 2016-06-14 10:12 ` [PATCH 1/2] ratelimit: Extend to print suppressed messages on release Borislav Petkov ` (2 more replies) 0 siblings, 3 replies; 9+ messages in thread From: Borislav Petkov @ 2016-06-14 10:12 UTC (permalink / raw) To: Linus Torvalds, Steven Rostedt Cc: Greg Kroah-Hartman, Ingo Molnar, Peter Zijlstra, Andrew Morton, Uwe Kleine-König, LKML From: Borislav Petkov <bp@suse.de> Ok, so how about these two? Rostedt is busy so I took Linus' old patch and Steven's last v2 and split and extended them with the comments people had on the last thread: https://lkml.kernel.org/r/20160425145606.598329f2@gandalf.local.home I hope, at least. So it is ratelimiting by default, with "on" and "off" cmdline options. I called the option somewhat a bit shorter too: "printk.kmsg" The current use cases of this and of which I'm aware are: * debug the kernel and thus shut up all interfering input from userspace, i.e. boot with "printk.kmsg=off" * debug userspace (and by that I mean systemd) by booting with "printk.kmsg=on" so that the ratelimiting is disabled and the kernel log gets all the spew. Thoughts? Thanks. Borislav Petkov (2): ratelimit: Extend to print suppressed messages on release printk: Add kernel parameter to control writes to /dev/kmsg Documentation/kernel-parameters.txt | 6 ++++ include/linux/ratelimit.h | 36 +++++++++++++++++++---- kernel/printk/printk.c | 57 +++++++++++++++++++++++++++++++------ lib/ratelimit.c | 6 ++-- 4 files changed, 90 insertions(+), 15 deletions(-) -- 2.7.3 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] ratelimit: Extend to print suppressed messages on release 2016-06-14 10:12 [PATCH 0/2] printk.kmsg: Ratelimit it by default Borislav Petkov @ 2016-06-14 10:12 ` Borislav Petkov 2016-06-14 10:12 ` [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg Borislav Petkov 2016-06-16 1:41 ` [PATCH 0/2] printk.kmsg: Ratelimit it by default Linus Torvalds 2 siblings, 0 replies; 9+ messages in thread From: Borislav Petkov @ 2016-06-14 10:12 UTC (permalink / raw) To: Linus Torvalds, Steven Rostedt Cc: Greg Kroah-Hartman, Ingo Molnar, Peter Zijlstra, Andrew Morton, Uwe Kleine-König, LKML From: Borislav Petkov <bp@suse.de> Extend the ratelimiting facility to print the amount of suppressed lines when it is being released. Separated from a previous patch by Linus. Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> --- include/linux/ratelimit.h | 36 +++++++++++++++++++++++++++++++----- lib/ratelimit.c | 6 ++++-- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h index 18102529254e..a68a56d223c2 100644 --- a/include/linux/ratelimit.h +++ b/include/linux/ratelimit.h @@ -2,11 +2,15 @@ #define _LINUX_RATELIMIT_H #include <linux/param.h> +#include <linux/sched.h> #include <linux/spinlock.h> #define DEFAULT_RATELIMIT_INTERVAL (5 * HZ) #define DEFAULT_RATELIMIT_BURST 10 +/* issue num suppressed message on exit */ +#define RATELIMIT_MSG_ON_RELEASE BIT(0) + struct ratelimit_state { raw_spinlock_t lock; /* protect the state */ @@ -15,6 +19,7 @@ struct ratelimit_state { int printed; int missed; unsigned long begin; + unsigned long flags; }; #define RATELIMIT_STATE_INIT(name, interval_init, burst_init) { \ @@ -34,12 +39,33 @@ struct ratelimit_state { static inline void ratelimit_state_init(struct ratelimit_state *rs, int interval, int burst) { + memset(rs, 0, sizeof(*rs)); + raw_spin_lock_init(&rs->lock); - rs->interval = interval; - rs->burst = burst; - rs->printed = 0; - rs->missed = 0; - rs->begin = 0; + rs->interval = interval; + rs->burst = burst; +} + +static inline void ratelimit_default_init(struct ratelimit_state *rs) +{ + return ratelimit_state_init(rs, DEFAULT_RATELIMIT_INTERVAL, + DEFAULT_RATELIMIT_BURST); +} + +static inline void ratelimit_state_exit(struct ratelimit_state *rs) +{ + if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) + return; + + if (rs->missed) + printk(KERN_WARNING "%s: %d callbacks suppressed\n", + current->comm, rs->missed); +} + +static inline void +ratelimit_set_flags(struct ratelimit_state *rs, unsigned long flags) +{ + rs->flags = flags; } extern struct ratelimit_state printk_ratelimit_state; diff --git a/lib/ratelimit.c b/lib/ratelimit.c index 2c5de86460c5..b753f0cfb00b 100644 --- a/lib/ratelimit.c +++ b/lib/ratelimit.c @@ -46,12 +46,14 @@ int ___ratelimit(struct ratelimit_state *rs, const char *func) rs->begin = jiffies; if (time_is_before_jiffies(rs->begin + rs->interval)) { - if (rs->missed) + if (rs->missed && !(rs->flags & RATELIMIT_MSG_ON_RELEASE)) printk(KERN_WARNING "%s: %d callbacks suppressed\n", func, rs->missed); rs->begin = jiffies; rs->printed = 0; - rs->missed = 0; + + if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) + rs->missed = 0; } if (rs->burst && rs->burst > rs->printed) { rs->printed++; -- 2.7.3 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg 2016-06-14 10:12 [PATCH 0/2] printk.kmsg: Ratelimit it by default Borislav Petkov 2016-06-14 10:12 ` [PATCH 1/2] ratelimit: Extend to print suppressed messages on release Borislav Petkov @ 2016-06-14 10:12 ` Borislav Petkov 2016-06-14 10:21 ` Ingo Molnar 2016-06-16 1:41 ` [PATCH 0/2] printk.kmsg: Ratelimit it by default Linus Torvalds 2 siblings, 1 reply; 9+ messages in thread From: Borislav Petkov @ 2016-06-14 10:12 UTC (permalink / raw) To: Linus Torvalds, Steven Rostedt Cc: Greg Kroah-Hartman, Ingo Molnar, Peter Zijlstra, Andrew Morton, Uwe Kleine-König, LKML From: Borislav Petkov <bp@suse.de> 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 <bp@suse.de> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Steven Rostedt <rostedt@goodmis.org> --- 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 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg 2016-06-14 10:12 ` [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg Borislav Petkov @ 2016-06-14 10:21 ` Ingo Molnar 2016-06-14 18:14 ` Steven Rostedt 0 siblings, 1 reply; 9+ messages in thread From: Ingo Molnar @ 2016-06-14 10:21 UTC (permalink / raw) To: Borislav Petkov Cc: Linus Torvalds, Steven Rostedt, Greg Kroah-Hartman, Peter Zijlstra, Andrew Morton, Uwe Kleine-König, LKML * Borislav Petkov <bp@alien8.de> wrote: > From: Borislav Petkov <bp@suse.de> > > 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 Please also add a sysctl! I *so* want to enable this on distro kernels without having to reboot the kernel... Thanks, Ingo ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg 2016-06-14 10:21 ` Ingo Molnar @ 2016-06-14 18:14 ` Steven Rostedt 2016-06-14 18:30 ` Borislav Petkov 2016-06-16 1:40 ` Linus Torvalds 0 siblings, 2 replies; 9+ messages in thread From: Steven Rostedt @ 2016-06-14 18:14 UTC (permalink / raw) To: Ingo Molnar Cc: Borislav Petkov, Linus Torvalds, Greg Kroah-Hartman, Peter Zijlstra, Andrew Morton, Uwe Kleine-König, LKML On Tue, 14 Jun 2016 12:21:35 +0200 Ingo Molnar <mingo@kernel.org> wrote: > * Borislav Petkov <bp@alien8.de> wrote: > > > From: Borislav Petkov <bp@suse.de> > > > > 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 > > Please also add a sysctl! > > I *so* want to enable this on distro kernels without having to reboot the > kernel... > But can we make it a one way feature (or a kernel parameter to do so?) that will prevent userspace from enabling it after it's been disabled. -- Steve ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg 2016-06-14 18:14 ` Steven Rostedt @ 2016-06-14 18:30 ` Borislav Petkov 2016-06-16 1:40 ` Linus Torvalds 1 sibling, 0 replies; 9+ messages in thread From: Borislav Petkov @ 2016-06-14 18:30 UTC (permalink / raw) To: Steven Rostedt Cc: Ingo Molnar, Linus Torvalds, Greg Kroah-Hartman, Peter Zijlstra, Andrew Morton, Uwe Kleine-König, LKML On Tue, Jun 14, 2016 at 02:14:56PM -0400, Steven Rostedt wrote: > But can we make it a one way feature (or a kernel parameter to do so?) > that will prevent userspace from enabling it after it's been disabled. You mean to be able to do boot with: "printk.kmsg=off_and_i_mean_it" which then disables the sysctl? Are you suspecting insolent userspace reenabling it? -- Regards/Gruss, Boris. ECO tip #101: Trim your mails when you reply. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg 2016-06-14 18:14 ` Steven Rostedt 2016-06-14 18:30 ` Borislav Petkov @ 2016-06-16 1:40 ` Linus Torvalds 2016-06-16 9:51 ` Borislav Petkov 1 sibling, 1 reply; 9+ messages in thread From: Linus Torvalds @ 2016-06-16 1:40 UTC (permalink / raw) To: Steven Rostedt Cc: Ingo Molnar, Borislav Petkov, Greg Kroah-Hartman, Peter Zijlstra, Andrew Morton, Uwe Kleine-König, LKML On Tue, Jun 14, 2016 at 8:14 AM, Steven Rostedt <rostedt@goodmis.org> wrote: >> >> Please also add a sysctl! >> >> I *so* want to enable this on distro kernels without having to reboot the >> kernel... >> > > But can we make it a one way feature (or a kernel parameter to do so?) > that will prevent userspace from enabling it after it's been disabled. Possibly we could just say that if a kernel command line option has been given, that is absolute. And then a sysctl for when you do *not* explicitly set if on the kernel command line? Linus ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg 2016-06-16 1:40 ` Linus Torvalds @ 2016-06-16 9:51 ` Borislav Petkov 0 siblings, 0 replies; 9+ messages in thread From: Borislav Petkov @ 2016-06-16 9:51 UTC (permalink / raw) To: Linus Torvalds Cc: Steven Rostedt, Ingo Molnar, Greg Kroah-Hartman, Peter Zijlstra, Andrew Morton, Uwe Kleine-König, LKML On Wed, Jun 15, 2016 at 03:40:04PM -1000, Linus Torvalds wrote: > Possibly we could just say that if a kernel command line option has > been given, that is absolute. > > And then a sysctl for when you do *not* explicitly set if on the > kernel command line? Ok, how about this ontop? It is only lightly tested in a vm but basically I'm using the second byte of devkmsg_log to set a bit in there and the sysctl handler looks at it. It is also visible in sysctl and we know it has been cmdline-disabled: $ cat /proc/sys/kernel/printk_kmsg 256 --- diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index a3683ce2a2f3..02fe4562953f 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -752,6 +752,19 @@ send before ratelimiting kicks in. ============================================================== +printk_kmsg: + +Control the logging to /dev/kmsg from userspace: + +0: default, ratelimited +1: unlimited logging to /dev/kmsg from userspace +2: logging to /dev/kmsg disabled + +The kernel command line parameter printk.kmsg= overrides this setting +and once set, it cannot be changed by this sysctl interface anymore. + +============================================================== + randomize_va_space: This option can be used to select the type of process address diff --git a/include/linux/printk.h b/include/linux/printk.h index f4da695fd615..bcf72e756122 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -171,6 +171,12 @@ extern bool printk_timed_ratelimit(unsigned long *caller_jiffies, extern int printk_delay_msec; extern int dmesg_restrict; extern int kptr_restrict; +extern unsigned int devkmsg_log; + +struct ctl_table; + +int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos); extern void wake_up_klogd(void); diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 33701a166f26..9f0a885c2718 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -86,12 +86,15 @@ static struct lockdep_map console_lock_dep_map = { }; #endif -#define DEVKMSG_LOG_RATELIMIT 0 -#define DEVKMSG_LOG_ON 1 -#define DEVKMSG_LOG_OFF 2 +#define DEVKMSG_LOG_RATELIMIT 0 +#define DEVKMSG_LOG_ON 1 +#define DEVKMSG_LOG_OFF 2 +#define DEVKMSG_LOCK (1 << 8) +#define DEVKMSG_LOG_MASK (DEVKMSG_LOCK - 1) +#define DEVKMSG_LOCKED_MASK ~DEVKMSG_LOG_MASK /* DEVKMSG_LOG_RATELIMIT by default */ -static unsigned int __read_mostly devkmsg_log; +unsigned int __read_mostly devkmsg_log; static int __init control_devkmsg(char *str) { if (!str) @@ -101,14 +104,30 @@ static int __init control_devkmsg(char *str) devkmsg_log = DEVKMSG_LOG_ON; else if (!strncmp(str, "off", 3)) devkmsg_log = DEVKMSG_LOG_OFF; + else if (!strncmp(str, "ratelimit", 9)) + devkmsg_log = DEVKMSG_LOG_RATELIMIT; else return -EINVAL; + /* Sysctl cannot change it anymore. */ + devkmsg_log |= DEVKMSG_LOCK; + return 0; } __setup("printk.kmsg=", control_devkmsg); +int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + if (devkmsg_log & DEVKMSG_LOCKED_MASK) { + if (write) + return -EINVAL; + } + + return proc_dointvec_minmax(table, write, buffer, lenp, ppos); +} + /* * Number of registered extended console drivers. * @@ -656,11 +675,12 @@ static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from) return -EINVAL; /* Ignore when user logging is disabled. */ - if (devkmsg_log == DEVKMSG_LOG_OFF) + if ((devkmsg_log & DEVKMSG_LOG_MASK) == 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 ((system_state != SYSTEM_BOOTING) && + ((devkmsg_log & DEVKMSG_LOG_MASK) != DEVKMSG_LOG_ON)) { if (!___ratelimit(&user->rs, current->comm)) return ret; } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 87b2fc38398b..a29d6c4fa86c 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -814,6 +814,15 @@ static struct ctl_table kern_table[] = { .extra2 = &ten_thousand, }, { + .procname = "printk_kmsg", + .data = &devkmsg_log, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = devkmsg_sysctl_set_loglvl, + .extra1 = &zero, + .extra2 = &two, + }, + { .procname = "dmesg_restrict", .data = &dmesg_restrict, .maxlen = sizeof(int), -- Regards/Gruss, Boris. ECO tip #101: Trim your mails when you reply. ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 0/2] printk.kmsg: Ratelimit it by default 2016-06-14 10:12 [PATCH 0/2] printk.kmsg: Ratelimit it by default Borislav Petkov 2016-06-14 10:12 ` [PATCH 1/2] ratelimit: Extend to print suppressed messages on release Borislav Petkov 2016-06-14 10:12 ` [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg Borislav Petkov @ 2016-06-16 1:41 ` Linus Torvalds 2 siblings, 0 replies; 9+ messages in thread From: Linus Torvalds @ 2016-06-16 1:41 UTC (permalink / raw) To: Borislav Petkov Cc: Steven Rostedt, Greg Kroah-Hartman, Ingo Molnar, Peter Zijlstra, Andrew Morton, Uwe Kleine-König, LKML On Tue, Jun 14, 2016 at 12:12 AM, Borislav Petkov <bp@alien8.de> wrote: > > Ok, so how about these two? Looks ok to me. Ack. Linus ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2016-06-16 9:51 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-06-14 10:12 [PATCH 0/2] printk.kmsg: Ratelimit it by default Borislav Petkov 2016-06-14 10:12 ` [PATCH 1/2] ratelimit: Extend to print suppressed messages on release Borislav Petkov 2016-06-14 10:12 ` [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg Borislav Petkov 2016-06-14 10:21 ` Ingo Molnar 2016-06-14 18:14 ` Steven Rostedt 2016-06-14 18:30 ` Borislav Petkov 2016-06-16 1:40 ` Linus Torvalds 2016-06-16 9:51 ` Borislav Petkov 2016-06-16 1:41 ` [PATCH 0/2] printk.kmsg: Ratelimit it by default Linus Torvalds
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).