tracing: sanitize value returned from write(trace_marker, "...", len)
PATCH 1/1 tracing: sanitize value returned from write(trace_marker, "...", len)
When userspace code writes non-new-line-terminated string to trace_marker file, write handler appends new-line and returns number of bytes written to trace buffer, sowrite(fd, "abc", 3) will return 4
That's unexpected and unfortunately it confuses glibc's fprintf function.
Example:
int main() {
fprintf(stderr, "abc");
return 0;
}
results in infinite loop:write(fd, "abc", 3) = 4write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0
(...)
...and kernel trace buffer full of empty markers.
Fix it by sanitizing write return value.
--- kernel/trace/trace.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-)
kernel/trace/trace.c +8 -3
@@ -3499,6 +3499,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *fpos) { char *buf; +size_t written;if (tracing_disabled)return -EINVAL ;
@@ -3520,11 +3521,15 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, }else buf[cnt] ='\0' ; - cnt =mark_printk ("%s" , buf); + written =mark_printk ("%s" , buf);kfree (buf); - *fpos += cnt; + *fpos += written; -return cnt; +/* don't tell userspace we wrote more - it might confuse them */ +if (written > cnt) + written = cnt; + +return written; }static int tracing_clock_show (struct seq_file *m,void *v)
Signature · 1 line
1.7.1.1
PATCH v2 1/1 tracing: sanitize value returned from write(trace_marker, "...", len)
Now with corrected changelog.
---
From: Marcin Slusarz <[email protected]>
Subject: [PATCH] tracing: sanitize value returned from write(trace_marker, "...", len)
When userspace code writes non-new-line-terminated string to trace_marker file, write handler appends new-line and returns number of bytes written to trace buffer, sowrite(fd, "abc", 3) will return 4
That's unexpected and unfortunately it confuses glibc's fprintf function.
Example:
int main() {
fprintf(stderr, "abc");
return 0;
}
$ gcc test.c -o test $ echo mmiotrace > /sys/kernel/debug/tracing/current_tracer $ ./test 2>/sys/kernel/debug/tracing/trace_marker
results in infinite loop:write(fd, "abc", 3) = 4write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0
(...)
...and kernel trace buffer full of empty markers.
Fix it by sanitizing write return value.
--- kernel/trace/trace.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-)
kernel/trace/trace.c +8 -3
@@ -3499,6 +3499,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *fpos) { char *buf; +size_t written;if (tracing_disabled)return -EINVAL ;
@@ -3520,11 +3521,15 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, }else buf[cnt] ='\0' ; - cnt =mark_printk ("%s" , buf); + written =mark_printk ("%s" , buf);kfree (buf); - *fpos += cnt; + *fpos += written; -return cnt; +/* don't tell userspace we wrote more - it might confuse them */ +if (written > cnt) + written = cnt; + +return written; }static int tracing_clock_show (struct seq_file *m,void *v)
Signature · 1 line
1.7.1.1
[tip:perf/urgent] tracing: Sanitize value returned from write(trace_marker, "...", len)
Commit-ID: 1aa54bca6ee0d07ebcafb8ca8074b624d80724aa Gitweb: http://git.kernel.org/tip/1aa54bca6ee0d07ebcafb8ca8074b624d80724aa Author: Marcin Slusarz <[email protected]> AuthorDate: Wed, 28 Jul 2010 01:18:01 +0200 Committer: Steven Rostedt <[email protected]> CommitDate: Fri, 13 Aug 2010 15:23:16 -0400
tracing: Sanitize value returned from write(trace_marker, "...", len)
When userspace code writes non-new-line-terminated string to trace_marker file, write handler appends new-line and returns number of bytes written to trace buffer, sowrite(fd, "abc", 3) will return 4
That's unexpected and unfortunately it confuses glibc's fprintf function.
Example:
int main() {
fprintf(stderr, "abc");
return 0;
}
$ gcc test.c -o test $ echo mmiotrace > /sys/kernel/debug/tracing/current_tracer $ ./test 2>/sys/kernel/debug/tracing/trace_marker
results in infinite loop:write(fd, "abc", 3) = 4write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0write(fd, "", 1) = 0
(...)
...and kernel trace buffer full of empty markers.
Fix it by sanitizing write return value.
LKML-Reference: <[email protected]>
--- kernel/trace/trace.c | 11 ++++++++--- 1 files changed, 8 insertions(+), 3 deletions(-)
kernel/trace/trace.c +8 -3
@@ -3498,6 +3498,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *fpos) { char *buf; +size_t written;if (tracing_disabled)return -EINVAL ;
@@ -3519,11 +3520,15 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, }else buf[cnt] ='\0' ; - cnt =mark_printk ("%s" , buf); + written =mark_printk ("%s" , buf);kfree (buf); - *fpos += cnt; + *fpos += written; -return cnt; +/* don't tell userspace we wrote more - it might confuse them */ +if (written > cnt) + written = cnt; + +return written; }static int tracing_clock_show (struct seq_file *m,void *v)