From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org
Cc: Ingo Molnar <mingo@kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
Jiri Kosina <jkosina@suse.cz>, Petr Mladek <pmladek@suse.cz>
Subject: [PATCH 19/26 v5] tracing: Use trace_seq_used() and seq_buf_used() instead of len
Date: Fri, 14 Nov 2014 23:59:06 -0500 [thread overview]
Message-ID: <20141115050603.904875201@goodmis.org> (raw)
In-Reply-To: 20141115045847.712848224@goodmis.org
[-- Attachment #1: 0019-tracing-Use-trace_seq_used-and-seq_buf_used-instead-.patch --]
[-- Type: text/plain, Size: 7885 bytes --]
From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>
As the seq_buf->len will soon be +1 size when there's an overflow, we
must use trace_seq_used() or seq_buf_used() methods to get the real
length. This will prevent buffer overflow issues if just the len
of the seq_buf descriptor is used to copy memory.
Link: http://lkml.kernel.org/r/20141114121911.09ba3d38@gandalf.local.home
Reported-by: Petr Mladek <pmladek@suse.cz>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
include/linux/trace_seq.h | 20 +++++++++++++++-
kernel/trace/seq_buf.c | 2 +-
kernel/trace/trace.c | 44 ++++++++++++++++++++++++------------
kernel/trace/trace_events.c | 9 +++++---
kernel/trace/trace_functions_graph.c | 5 +++-
kernel/trace/trace_seq.c | 2 +-
6 files changed, 60 insertions(+), 22 deletions(-)
diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h
index 85d37106be3d..cfaf5a1d4bad 100644
--- a/include/linux/trace_seq.h
+++ b/include/linux/trace_seq.h
@@ -24,6 +24,24 @@ trace_seq_init(struct trace_seq *s)
}
/**
+ * trace_seq_used - amount of actual data written to buffer
+ * @s: trace sequence descriptor
+ *
+ * Returns the amount of data written to the buffer.
+ *
+ * IMPORTANT!
+ *
+ * Use this instead of @s->seq.len if you need to pass the amount
+ * of data from the buffer to another buffer (userspace, or what not).
+ * The @s->seq.len on overflow is bigger than the buffer size and
+ * using it can cause access to undefined memory.
+ */
+static inline int trace_seq_used(struct trace_seq *s)
+{
+ return seq_buf_used(&s->seq);
+}
+
+/**
* trace_seq_buffer_ptr - return pointer to next location in buffer
* @s: trace sequence descriptor
*
@@ -35,7 +53,7 @@ trace_seq_init(struct trace_seq *s)
static inline unsigned char *
trace_seq_buffer_ptr(struct trace_seq *s)
{
- return s->buffer + s->seq.len;
+ return s->buffer + seq_buf_used(&s->seq);
}
/**
diff --git a/kernel/trace/seq_buf.c b/kernel/trace/seq_buf.c
index 9ec5305d9da7..ce17f65268ed 100644
--- a/kernel/trace/seq_buf.c
+++ b/kernel/trace/seq_buf.c
@@ -328,7 +328,7 @@ int seq_buf_to_user(struct seq_buf *s, char __user *ubuf, int cnt)
if (s->len <= s->readpos)
return -EBUSY;
- len = s->len - s->readpos;
+ len = seq_buf_used(s) - s->readpos;
if (cnt > len)
cnt = len;
ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 7d7a07e9b9e9..9f1ffc707f3b 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -944,10 +944,10 @@ static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
{
int len;
- if (s->seq.len <= s->seq.readpos)
+ if (trace_seq_used(s) <= s->seq.readpos)
return -EBUSY;
- len = s->seq.len - s->seq.readpos;
+ len = trace_seq_used(s) - s->seq.readpos;
if (cnt > len)
cnt = len;
memcpy(buf, s->buffer + s->seq.readpos, cnt);
@@ -4514,18 +4514,18 @@ waitagain:
trace_access_lock(iter->cpu_file);
while (trace_find_next_entry_inc(iter) != NULL) {
enum print_line_t ret;
- int len = iter->seq.seq.len;
+ int save_len = iter->seq.seq.len;
ret = print_trace_line(iter);
if (ret == TRACE_TYPE_PARTIAL_LINE) {
/* don't print partial lines */
- iter->seq.seq.len = len;
+ iter->seq.seq.len = save_len;
break;
}
if (ret != TRACE_TYPE_NO_CONSUME)
trace_consume(iter);
- if (iter->seq.seq.len >= cnt)
+ if (trace_seq_used(&iter->seq) >= cnt)
break;
/*
@@ -4541,7 +4541,7 @@ waitagain:
/* Now copy what we have to the user */
sret = trace_seq_to_user(&iter->seq, ubuf, cnt);
- if (iter->seq.seq.readpos >= iter->seq.seq.len)
+ if (iter->seq.seq.readpos >= trace_seq_used(&iter->seq))
trace_seq_init(&iter->seq);
/*
@@ -4575,20 +4575,33 @@ static size_t
tracing_fill_pipe_page(size_t rem, struct trace_iterator *iter)
{
size_t count;
+ int save_len;
int ret;
/* Seq buffer is page-sized, exactly what we need. */
for (;;) {
- count = iter->seq.seq.len;
+ save_len = iter->seq.seq.len;
ret = print_trace_line(iter);
- count = iter->seq.seq.len - count;
- if (rem < count) {
- rem = 0;
- iter->seq.seq.len -= count;
+
+ if (trace_seq_has_overflowed(&iter->seq)) {
+ iter->seq.seq.len = save_len;
break;
}
+
+ /*
+ * This should not be hit, because it should only
+ * be set if the iter->seq overflowed. But check it
+ * anyway to be safe.
+ */
if (ret == TRACE_TYPE_PARTIAL_LINE) {
- iter->seq.seq.len -= count;
+ iter->seq.seq.len = save_len;
+ break;
+ }
+
+ count = trace_seq_used(&iter->seq) - save_len;
+ if (rem < count) {
+ rem = 0;
+ iter->seq.seq.len = save_len;;
break;
}
@@ -4669,13 +4682,13 @@ static ssize_t tracing_splice_read_pipe(struct file *filp,
/* Copy the data into the page, so we can start over. */
ret = trace_seq_to_buffer(&iter->seq,
page_address(spd.pages[i]),
- iter->seq.seq.len);
+ trace_seq_used(&iter->seq));
if (ret < 0) {
__free_page(spd.pages[i]);
break;
}
spd.partial[i].offset = 0;
- spd.partial[i].len = iter->seq.seq.len;
+ spd.partial[i].len = trace_seq_used(&iter->seq);
trace_seq_init(&iter->seq);
}
@@ -5676,7 +5689,8 @@ tracing_stats_read(struct file *filp, char __user *ubuf,
cnt = ring_buffer_read_events_cpu(trace_buf->buffer, cpu);
trace_seq_printf(s, "read events: %ld\n", cnt);
- count = simple_read_from_buffer(ubuf, count, ppos, s->buffer, s->seq.len);
+ count = simple_read_from_buffer(ubuf, count, ppos,
+ s->buffer, trace_seq_used(s));
kfree(s);
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 4d0067dd7f88..935cbea78532 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -1044,7 +1044,8 @@ event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
mutex_unlock(&event_mutex);
if (file)
- r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->seq.len);
+ r = simple_read_from_buffer(ubuf, cnt, ppos,
+ s->buffer, trace_seq_used(s));
kfree(s);
@@ -1210,7 +1211,8 @@ subsystem_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
trace_seq_init(s);
print_subsystem_event_filter(system, s);
- r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->seq.len);
+ r = simple_read_from_buffer(ubuf, cnt, ppos,
+ s->buffer, trace_seq_used(s));
kfree(s);
@@ -1265,7 +1267,8 @@ show_header(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
trace_seq_init(s);
func(s);
- r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->seq.len);
+ r = simple_read_from_buffer(ubuf, cnt, ppos,
+ s->buffer, trace_seq_used(s));
kfree(s);
diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 6d1342ae7a44..ec35468349a7 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -1153,6 +1153,9 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
return ret;
}
+ if (trace_seq_has_overflowed(s))
+ goto out;
+
/* Strip ending newline */
if (s->buffer[s->seq.len - 1] == '\n') {
s->buffer[s->seq.len - 1] = '\0';
@@ -1160,7 +1163,7 @@ print_graph_comment(struct trace_seq *s, struct trace_entry *ent,
}
trace_seq_puts(s, " */\n");
-
+ out:
return trace_handle_return(s);
}
diff --git a/kernel/trace/trace_seq.c b/kernel/trace/trace_seq.c
index 087fa514069d..0c7aab4dd94f 100644
--- a/kernel/trace/trace_seq.c
+++ b/kernel/trace/trace_seq.c
@@ -30,7 +30,7 @@
#define TRACE_SEQ_BUF_LEFT(s) seq_buf_buffer_left(&(s)->seq)
/* How much buffer is written? */
-#define TRACE_SEQ_BUF_USED(s) min((s)->seq.len, (unsigned int)(PAGE_SIZE - 1))
+#define TRACE_SEQ_BUF_USED(s) seq_buf_used(&(s)->seq)
/*
* trace_seq should work with being initialized with 0s.
--
2.1.1
next prev parent reply other threads:[~2014-11-15 5:07 UTC|newest]
Thread overview: 70+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-11-15 4:58 [PATCH 00/26 v5] trace-seq/seq-buf/x86/printk: Print all stacks from NMI safely Steven Rostedt
2014-11-15 4:58 ` [PATCH 01/26 v5] tracing: Fix trace_seq_bitmask() to start at current position Steven Rostedt
2014-11-15 4:58 ` [PATCH 02/26 v5] tracing: Add trace_seq_has_overflowed() and trace_handle_return() Steven Rostedt
2014-11-15 4:58 ` [PATCH 03/26 v5] blktrace/tracing: Use trace_seq_has_overflowed() helper function Steven Rostedt
2014-11-15 4:58 ` [PATCH 04/26 v5] ring-buffer: Remove check of trace_seq_{puts,printf}() return values Steven Rostedt
2014-11-15 4:58 ` [PATCH 05/26 v5] tracing: Have branch tracer use trace_handle_return() helper function Steven Rostedt
2014-11-15 4:58 ` [PATCH 06/26 v5] tracing: Have function_graph use trace_seq_has_overflowed() Steven Rostedt
2014-11-15 4:58 ` [PATCH 07/26 v5] kprobes/tracing: Use trace_seq_has_overflowed() for overflow checks Steven Rostedt
2014-11-18 14:02 ` Petr Mladek
2014-11-15 4:58 ` [PATCH 08/26 v5] tracing: Do not check return values of trace_seq_p*() for mmio tracer Steven Rostedt
2014-11-18 14:06 ` Petr Mladek
2014-11-15 4:58 ` [PATCH 09/26 v5] tracing/probes: Do not use return value of trace_seq_printf() Steven Rostedt
2014-11-18 14:09 ` Petr Mladek
2014-11-15 4:58 ` [PATCH 10/26 v5] tracing/uprobes: Do not use return values " Steven Rostedt
2014-11-17 5:28 ` Masami Hiramatsu
2014-11-17 5:58 ` Srikar Dronamraju
2014-11-18 14:13 ` Petr Mladek
2014-11-15 4:58 ` [PATCH 11/26 v5] tracing: Do not use return values of trace_seq_printf() in syscall tracing Steven Rostedt
2014-11-15 4:58 ` [PATCH 12/26 v5] tracing: Remove return values of most trace_seq_*() functions Steven Rostedt
2014-11-18 14:18 ` Petr Mladek
2014-11-15 4:59 ` [PATCH 13/26 v5] tracing: Fix return value of ftrace_raw_output_prep() Steven Rostedt
2014-11-18 14:24 ` Petr Mladek
2014-11-15 4:59 ` [PATCH 14/26 v5] tracing: Create seq_buf layer in trace_seq Steven Rostedt
2014-11-19 14:51 ` Petr Mladek
2014-11-19 15:08 ` Steven Rostedt
2014-11-15 4:59 ` [PATCH 15/26 v5] tracing: Convert seq_buf_path() to be like seq_path() Steven Rostedt
2014-11-15 4:59 ` [PATCH 16/26 v5] tracing: Convert seq_buf fields to be like seq_file fields Steven Rostedt
2014-11-15 4:59 ` [PATCH 17/26 v5] tracing: Add a seq_buf_clear() helper and clear len and readpos in init Steven Rostedt
2014-11-15 4:59 ` [PATCH 18/26 v5] seq_buf: Create seq_buf_used() to find out how much was written Steven Rostedt
2014-11-18 15:02 ` Petr Mladek
2014-11-19 15:49 ` Steven Rostedt
2014-11-19 16:30 ` Petr Mladek
2014-11-15 4:59 ` Steven Rostedt [this message]
2014-11-17 17:32 ` [PATCH 19/26 v5] tracing: Use trace_seq_used() and seq_buf_used() instead of len Steven Rostedt
2014-11-17 19:11 ` [PATCH 1/2] tracing: Clean up tracing_fill_pipe_page() Steven Rostedt
2014-11-18 16:15 ` Petr Mladek
2014-11-19 16:17 ` Steven Rostedt
2014-11-19 16:51 ` Petr Mladek
2014-11-19 17:12 ` Steven Rostedt
2014-11-17 19:12 ` [PATCH 2/2] tracing: Use trace_seq_used() and seq_buf_used() instead of len Steven Rostedt
2014-11-18 16:33 ` Petr Mladek
2014-11-18 17:37 ` Steven Rostedt
2014-11-19 11:40 ` Petr Mladek
2014-11-19 13:48 ` Steven Rostedt
2014-11-19 14:40 ` Petr Mladek
2014-11-19 15:01 ` Steven Rostedt
2014-11-19 16:00 ` Steven Rostedt
2014-11-19 16:44 ` Petr Mladek
2014-11-15 4:59 ` [PATCH 20/26 v5] seq_buf: Add seq_buf_can_fit() helper function Steven Rostedt
2014-11-17 17:36 ` Steven Rostedt
2014-11-18 0:07 ` Joe Perches
2014-11-18 0:27 ` Steven Rostedt
2014-11-18 0:35 ` Joe Perches
2014-11-18 0:56 ` Steven Rostedt
2014-11-18 1:07 ` Joe Perches
2014-11-18 1:24 ` Steven Rostedt
2014-11-18 1:48 ` Joe Perches
2014-11-18 2:37 ` Steven Rostedt
2014-11-18 2:50 ` Joe Perches
2014-11-18 3:00 ` Steven Rostedt
2014-11-18 16:40 ` Petr Mladek
2014-11-15 4:59 ` [PATCH 21/26 v5] tracing: Have seq_buf use full buffer Steven Rostedt
2014-11-15 4:59 ` [PATCH 22/26 v5] tracing: Add seq_buf_get_buf() and seq_buf_commit() helper functions Steven Rostedt
2014-11-15 4:59 ` [PATCH 23/26 v5] seq-buf: Make seq_buf_bprintf() conditional on CONFIG_BINARY_PRINTF Steven Rostedt
2014-11-15 4:59 ` [PATCH 24/26 v5] seq_buf: Move the seq_buf code to lib/ Steven Rostedt
2014-11-15 4:59 ` [PATCH 25/26 v5] printk: Add per_cpu printk func to allow printk to be diverted Steven Rostedt
2014-11-15 4:59 ` [PATCH 26/26 v5] x86/nmi: Perform a safe NMI stack trace on all CPUs Steven Rostedt
2014-11-18 17:02 ` Petr Mladek
2014-11-15 5:08 ` [PATCH 00/26 v5] trace-seq/seq-buf/x86/printk: Print all stacks from NMI safely Steven Rostedt
2014-11-18 3:21 ` Steven Rostedt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20141115050603.904875201@goodmis.org \
--to=rostedt@goodmis.org \
--cc=akpm@linux-foundation.org \
--cc=jkosina@suse.cz \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=pmladek@suse.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).