aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <bp@suse.de>2016-08-02 17:04:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-08-02 19:35:06 -0400
commit750afe7babd117daabebf4855da18e4418ea845e (patch)
tree21aaf3748d3afd3e880b6ef301128c5567a15956
parent6b1d174b0c27b5de421eda55c2731f32b6bd9852 (diff)
printk: add kernel parameter to control writes to /dev/kmsg
Add a "printk.devkmsg" kernel command line parameter which controls how userspace writes into /dev/kmsg. It has three options: * ratelimit - ratelimit logging from userspace. * on - unlimited logging from userspace * off - logging from userspace gets ignored The default setting is to ratelimit the messages written to it. This changes the kernel default setting of "on" to "ratelimit" and we do that because we want to keep userspace spamming /dev/kmsg to sane levels. This is especially moot when a small kernel log buffer wraps around and messages get lost. So the ratelimiting setting should be a sane setting where kernel messages should have a bit higher chance of survival from all the spamming. It additionally does not limit logging to /dev/kmsg while the system is booting if we haven't disabled it on the command line. Furthermore, we can control the logging from a lower priority sysctl interface - kernel.printk_devkmsg. That interface will succeed only if printk.devkmsg *hasn't* been supplied on the command line. If it has, then printk.devkmsg is a one-time setting which remains for the duration of the system lifetime. This "locking" of the setting is to prevent userspace from changing the logging on us through sysctl(2). This patch is based on previous patches from Linus and Steven. [bp@suse.de: fixes] Link: http://lkml.kernel.org/r/20160719072344.GC25563@nazgul.tnic Link: http://lkml.kernel.org/r/20160716061745.15795-3-bp@alien8.de Signed-off-by: Borislav Petkov <bp@suse.de> Cc: Dave Young <dyoung@redhat.com> Cc: Franck Bui <fbui@suse.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Ingo Molnar <mingo@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/kernel-parameters.txt7
-rw-r--r--Documentation/sysctl/kernel.txt14
-rw-r--r--include/linux/printk.h9
-rw-r--r--kernel/printk/printk.c142
-rw-r--r--kernel/sysctl.c7
5 files changed, 171 insertions, 8 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index e24aa11e8f8a..b240540e49f2 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3173,6 +3173,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
3173 Format: <bool> (1/Y/y=enable, 0/N/n=disable) 3173 Format: <bool> (1/Y/y=enable, 0/N/n=disable)
3174 default: disabled 3174 default: disabled
3175 3175
3176 printk.devkmsg={on,off,ratelimit}
3177 Control writing to /dev/kmsg.
3178 on - unlimited logging to /dev/kmsg from userspace
3179 off - logging to /dev/kmsg disabled
3180 ratelimit - ratelimit the logging
3181 Default: ratelimit
3182
3176 printk.time= Show timing data prefixed to each printk message line 3183 printk.time= Show timing data prefixed to each printk message line
3177 Format: <bool> (1/Y/y=enable, 0/N/n=disable) 3184 Format: <bool> (1/Y/y=enable, 0/N/n=disable)
3178 3185
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 33204604de6c..ffab8b5caa60 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -764,6 +764,20 @@ send before ratelimiting kicks in.
764 764
765============================================================== 765==============================================================
766 766
767printk_devkmsg:
768
769Control the logging to /dev/kmsg from userspace:
770
771ratelimit: default, ratelimited
772on: unlimited logging to /dev/kmsg from userspace
773off: logging to /dev/kmsg disabled
774
775The kernel command line parameter printk.devkmsg= overrides this and is
776a one-time setting until next reboot: once set, it cannot be changed by
777this sysctl interface anymore.
778
779==============================================================
780
767randomize_va_space: 781randomize_va_space:
768 782
769This option can be used to select the type of process address 783This option can be used to select the type of process address
diff --git a/include/linux/printk.h b/include/linux/printk.h
index c2158f0f1499..8dc155dab3ed 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -61,6 +61,11 @@ static inline void console_verbose(void)
61 console_loglevel = CONSOLE_LOGLEVEL_MOTORMOUTH; 61 console_loglevel = CONSOLE_LOGLEVEL_MOTORMOUTH;
62} 62}
63 63
64/* strlen("ratelimit") + 1 */
65#define DEVKMSG_STR_MAX_SIZE 10
66extern char devkmsg_log_str[];
67struct ctl_table;
68
64struct va_format { 69struct va_format {
65 const char *fmt; 70 const char *fmt;
66 va_list *va; 71 va_list *va;
@@ -175,6 +180,10 @@ extern int printk_delay_msec;
175extern int dmesg_restrict; 180extern int dmesg_restrict;
176extern int kptr_restrict; 181extern int kptr_restrict;
177 182
183extern int
184devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write, void __user *buf,
185 size_t *lenp, loff_t *ppos);
186
178extern void wake_up_klogd(void); 187extern void wake_up_klogd(void);
179 188
180char *log_buf_addr_get(void); 189char *log_buf_addr_get(void);
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 70c66c5ba212..a5ef95ca18c9 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -85,6 +85,111 @@ static struct lockdep_map console_lock_dep_map = {
85}; 85};
86#endif 86#endif
87 87
88enum devkmsg_log_bits {
89 __DEVKMSG_LOG_BIT_ON = 0,
90 __DEVKMSG_LOG_BIT_OFF,
91 __DEVKMSG_LOG_BIT_LOCK,
92};
93
94enum devkmsg_log_masks {
95 DEVKMSG_LOG_MASK_ON = BIT(__DEVKMSG_LOG_BIT_ON),
96 DEVKMSG_LOG_MASK_OFF = BIT(__DEVKMSG_LOG_BIT_OFF),
97 DEVKMSG_LOG_MASK_LOCK = BIT(__DEVKMSG_LOG_BIT_LOCK),
98};
99
100/* Keep both the 'on' and 'off' bits clear, i.e. ratelimit by default: */
101#define DEVKMSG_LOG_MASK_DEFAULT 0
102
103static unsigned int __read_mostly devkmsg_log = DEVKMSG_LOG_MASK_DEFAULT;
104
105static int __control_devkmsg(char *str)
106{
107 if (!str)
108 return -EINVAL;
109
110 if (!strncmp(str, "on", 2)) {
111 devkmsg_log = DEVKMSG_LOG_MASK_ON;
112 return 2;
113 } else if (!strncmp(str, "off", 3)) {
114 devkmsg_log = DEVKMSG_LOG_MASK_OFF;
115 return 3;
116 } else if (!strncmp(str, "ratelimit", 9)) {
117 devkmsg_log = DEVKMSG_LOG_MASK_DEFAULT;
118 return 9;
119 }
120 return -EINVAL;
121}
122
123static int __init control_devkmsg(char *str)
124{
125 if (__control_devkmsg(str) < 0)
126 return 1;
127
128 /*
129 * Set sysctl string accordingly:
130 */
131 if (devkmsg_log == DEVKMSG_LOG_MASK_ON) {
132 memset(devkmsg_log_str, 0, DEVKMSG_STR_MAX_SIZE);
133 strncpy(devkmsg_log_str, "on", 2);
134 } else if (devkmsg_log == DEVKMSG_LOG_MASK_OFF) {
135 memset(devkmsg_log_str, 0, DEVKMSG_STR_MAX_SIZE);
136 strncpy(devkmsg_log_str, "off", 3);
137 }
138 /* else "ratelimit" which is set by default. */
139
140 /*
141 * Sysctl cannot change it anymore. The kernel command line setting of
142 * this parameter is to force the setting to be permanent throughout the
143 * runtime of the system. This is a precation measure against userspace
144 * trying to be a smarta** and attempting to change it up on us.
145 */
146 devkmsg_log |= DEVKMSG_LOG_MASK_LOCK;
147
148 return 0;
149}
150__setup("printk.devkmsg=", control_devkmsg);
151
152char devkmsg_log_str[DEVKMSG_STR_MAX_SIZE] = "ratelimit";
153
154int devkmsg_sysctl_set_loglvl(struct ctl_table *table, int write,
155 void __user *buffer, size_t *lenp, loff_t *ppos)
156{
157 char old_str[DEVKMSG_STR_MAX_SIZE];
158 unsigned int old;
159 int err;
160
161 if (write) {
162 if (devkmsg_log & DEVKMSG_LOG_MASK_LOCK)
163 return -EINVAL;
164
165 old = devkmsg_log;
166 strncpy(old_str, devkmsg_log_str, DEVKMSG_STR_MAX_SIZE);
167 }
168
169 err = proc_dostring(table, write, buffer, lenp, ppos);
170 if (err)
171 return err;
172
173 if (write) {
174 err = __control_devkmsg(devkmsg_log_str);
175
176 /*
177 * Do not accept an unknown string OR a known string with
178 * trailing crap...
179 */
180 if (err < 0 || (err + 1 != *lenp)) {
181
182 /* ... and restore old setting. */
183 devkmsg_log = old;
184 strncpy(devkmsg_log_str, old_str, DEVKMSG_STR_MAX_SIZE);
185
186 return -EINVAL;
187 }
188 }
189
190 return 0;
191}
192
88/* 193/*
89 * Number of registered extended console drivers. 194 * Number of registered extended console drivers.
90 * 195 *
@@ -613,6 +718,7 @@ struct devkmsg_user {
613 u64 seq; 718 u64 seq;
614 u32 idx; 719 u32 idx;
615 enum log_flags prev; 720 enum log_flags prev;
721 struct ratelimit_state rs;
616 struct mutex lock; 722 struct mutex lock;
617 char buf[CONSOLE_EXT_LOG_MAX]; 723 char buf[CONSOLE_EXT_LOG_MAX];
618}; 724};
@@ -622,11 +728,24 @@ static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from)
622 char *buf, *line; 728 char *buf, *line;
623 int level = default_message_loglevel; 729 int level = default_message_loglevel;
624 int facility = 1; /* LOG_USER */ 730 int facility = 1; /* LOG_USER */
731 struct file *file = iocb->ki_filp;
732 struct devkmsg_user *user = file->private_data;
625 size_t len = iov_iter_count(from); 733 size_t len = iov_iter_count(from);
626 ssize_t ret = len; 734 ssize_t ret = len;
627 735
628 if (len > LOG_LINE_MAX) 736 if (!user || len > LOG_LINE_MAX)
629 return -EINVAL; 737 return -EINVAL;
738
739 /* Ignore when user logging is disabled. */
740 if (devkmsg_log & DEVKMSG_LOG_MASK_OFF)
741 return len;
742
743 /* Ratelimit when not explicitly enabled. */
744 if (!(devkmsg_log & DEVKMSG_LOG_MASK_ON)) {
745 if (!___ratelimit(&user->rs, current->comm))
746 return ret;
747 }
748
630 buf = kmalloc(len+1, GFP_KERNEL); 749 buf = kmalloc(len+1, GFP_KERNEL);
631 if (buf == NULL) 750 if (buf == NULL)
632 return -ENOMEM; 751 return -ENOMEM;
@@ -799,19 +918,24 @@ static int devkmsg_open(struct inode *inode, struct file *file)
799 struct devkmsg_user *user; 918 struct devkmsg_user *user;
800 int err; 919 int err;
801 920
802 /* write-only does not need any file context */ 921 if (devkmsg_log & DEVKMSG_LOG_MASK_OFF)
803 if ((file->f_flags & O_ACCMODE) == O_WRONLY) 922 return -EPERM;
804 return 0;
805 923
806 err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL, 924 /* write-only does not need any file context */
807 SYSLOG_FROM_READER); 925 if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
808 if (err) 926 err = check_syslog_permissions(SYSLOG_ACTION_READ_ALL,
809 return err; 927 SYSLOG_FROM_READER);
928 if (err)
929 return err;
930 }
810 931
811 user = kmalloc(sizeof(struct devkmsg_user), GFP_KERNEL); 932 user = kmalloc(sizeof(struct devkmsg_user), GFP_KERNEL);
812 if (!user) 933 if (!user)
813 return -ENOMEM; 934 return -ENOMEM;
814 935
936 ratelimit_default_init(&user->rs);
937 ratelimit_set_flags(&user->rs, RATELIMIT_MSG_ON_RELEASE);
938
815 mutex_init(&user->lock); 939 mutex_init(&user->lock);
816 940
817 raw_spin_lock_irq(&logbuf_lock); 941 raw_spin_lock_irq(&logbuf_lock);
@@ -830,6 +954,8 @@ static int devkmsg_release(struct inode *inode, struct file *file)
830 if (!user) 954 if (!user)
831 return 0; 955 return 0;
832 956
957 ratelimit_state_exit(&user->rs);
958
833 mutex_destroy(&user->lock); 959 mutex_destroy(&user->lock);
834 kfree(user); 960 kfree(user);
835 return 0; 961 return 0;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 53954631a4e1..b43d0b27c1fe 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -814,6 +814,13 @@ static struct ctl_table kern_table[] = {
814 .extra2 = &ten_thousand, 814 .extra2 = &ten_thousand,
815 }, 815 },
816 { 816 {
817 .procname = "printk_devkmsg",
818 .data = devkmsg_log_str,
819 .maxlen = DEVKMSG_STR_MAX_SIZE,
820 .mode = 0644,
821 .proc_handler = devkmsg_sysctl_set_loglvl,
822 },
823 {
817 .procname = "dmesg_restrict", 824 .procname = "dmesg_restrict",
818 .data = &dmesg_restrict, 825 .data = &dmesg_restrict,
819 .maxlen = sizeof(int), 826 .maxlen = sizeof(int),