linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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



  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).