printk.kmsg: Ratelimit it by default
Subsystems (4)
cover printk.kmsg: Ratelimit it by default
From: Borislav Petkov <[email protected]>
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/[email protected]
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(-)
Signature · 1 line
2.7.3
PATCH 1/2 ratelimit: Extend to print suppressed messages on release
From: Borislav Petkov <[email protected]>
Extend the ratelimiting facility to print the amount of suppressed lines when it is being released.
Separated from a previous patch by Linus.
--- include/linux/ratelimit.h | 36 +++++++++++++++++++++++++++++++----- lib/ratelimit.c | 6 ++++-- 2 files changed, 35 insertions(+), 7 deletions(-)
include/linux/ratelimit.h +31 -5
@@ -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;
lib/ratelimit.c +4 -2
@@ -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++;
Signature · 1 line
2.7.3
PATCH 2/2 printk: Add kernel parameter to control writes to /dev/kmsg
In reply to Borislav PetkovFrom: 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.
--- Documentation/kernel-parameters.txt | 6 ++++ kernel/printk/printk.c | 57 +++++++++++++++++++++++++++++++------ 2 files changed, 55 insertions(+), 8 deletions(-)
Documentation/kernel-parameters.txt +6 -0
@@ -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)
kernel/printk/printk.c +49 -8
96 lines not on this page · raw message
Signature · 1 line
2.7.3
Re: [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg
Quoted 7 lines · Borislav Petkov
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
Please also add a sysctl!
I *so* want to enable this on distro kernels without having to reboot the kernel...
Thanks,
Ingo
Steven Rostedt
reviewerRe: [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg
Quoted 7 lines · On Tue, 14 Jun 2016 12:21:35 +0200 Ingo Molnar <[email protected]> wrote:
Quoted 5 lines · Borislav Petkov
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:
Quoted 8 lines
Quoted 2 lines
* on - unlimited logging from userspace
* off - logging from userspace gets ignoredPlease 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
Re: [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg
Quoted 2 lines · Steven Rostedt
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?
Signature · 4 lines
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.Re: [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg
In reply to Steven RostedtQuoted 9 lines · Steven Rostedt
Quoted 6 lines
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
Re: [PATCH 2/2] printk: Add kernel parameter to control writes to /dev/kmsg
Quoted 5 lines · Linus Torvalds
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
---
Documentation/sysctl/kernel.txt +13 -0
@@ -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
include/linux/printk.h +6 -0
@@ -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 );
kernel/printk/printk.c +26 -6
@@ -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; }
kernel/sysctl.c +9 -0
@@ -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),
Signature · 4 lines
Regards/Gruss,
Boris.
ECO tip #101: Trim your mails when you reply.Quoted 2 lines · Borislav Petkov
Ok, so how about these two?
Looks ok to me. Ack.
Linus