summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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),