aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/printk.c
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2012-07-06 12:50:09 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-06 12:50:09 -0400
commitcb424ffe9f45ad80267f2a98fbd9bf21caa0ce22 (patch)
tree5cc5ff53498de2f5bd8262a467fdd39454360cdc /kernel/printk.c
parent43a73a50b352cd3df25b3ced72033942a6a0f919 (diff)
kmsg: properly handle concurrent non-blocking read() from /proc/kmsg
The /proc/kmsg read() interface is internally simply wired up to a sequence of syslog() syscalls, which might are racy between their checks and actions, regarding concurrency. In the (very uncommon) case of concurrent readers of /dev/kmsg, relying on usual O_NONBLOCK behavior, the recently introduced mutex might block an O_NONBLOCK reader in read(), when poll() returns for it, but another process has already read the data in the meantime. We've seen that while running artificial test setups and tools that "fight" about /proc/kmsg data. This restores the original /proc/kmsg behavior, where in case of concurrent read()s, poll() might wake up but the read() syscall will just return 0 to the caller, while another process has "stolen" the data. This is in the general case not the expected behavior, but it is the exact same one, that can easily be triggered with a 3.4 kernel, and some tools might just rely on it. The mutex is not needed, the original integrity issue which introduced it, is in the meantime covered by: "fill buffer with more than a single message for SYSLOG_ACTION_READ" 116e90b23f74d303e8d607c7a7d54f60f14ab9f2 Cc: Yuanhan Liu <yuanhan.liu@linux.intel.com> Acked-by: Jan Beulich <jbeulich@suse.com> Signed-off-by: Kay Sievers <kay@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel/printk.c')
-rw-r--r--kernel/printk.c9
1 files changed, 1 insertions, 8 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index 37cde752cb8a..be9a82b2f0b3 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1021,7 +1021,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
1021{ 1021{
1022 bool clear = false; 1022 bool clear = false;
1023 static int saved_console_loglevel = -1; 1023 static int saved_console_loglevel = -1;
1024 static DEFINE_MUTEX(syslog_mutex);
1025 int error; 1024 int error;
1026 1025
1027 error = check_syslog_permissions(type, from_file); 1026 error = check_syslog_permissions(type, from_file);
@@ -1048,17 +1047,11 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
1048 error = -EFAULT; 1047 error = -EFAULT;
1049 goto out; 1048 goto out;
1050 } 1049 }
1051 error = mutex_lock_interruptible(&syslog_mutex);
1052 if (error)
1053 goto out;
1054 error = wait_event_interruptible(log_wait, 1050 error = wait_event_interruptible(log_wait,
1055 syslog_seq != log_next_seq); 1051 syslog_seq != log_next_seq);
1056 if (error) { 1052 if (error)
1057 mutex_unlock(&syslog_mutex);
1058 goto out; 1053 goto out;
1059 }
1060 error = syslog_print(buf, len); 1054 error = syslog_print(buf, len);
1061 mutex_unlock(&syslog_mutex);
1062 break; 1055 break;
1063 /* Read/clear last kernel messages */ 1056 /* Read/clear last kernel messages */
1064 case SYSLOG_ACTION_READ_CLEAR: 1057 case SYSLOG_ACTION_READ_CLEAR: