| From 45d8b80c2ac5d21cd1e2954431fb676bc2b1e099 Mon Sep 17 00:00:00 2001 |
| From: "Steven Rostedt (VMware)" <rostedt@goodmis.org> |
| Date: Fri, 22 Dec 2017 20:32:35 -0500 |
| Subject: ring-buffer: Mask out the info bits when returning buffer page length |
| |
| From: Steven Rostedt (VMware) <rostedt@goodmis.org> |
| |
| commit 45d8b80c2ac5d21cd1e2954431fb676bc2b1e099 upstream. |
| |
| Two info bits were added to the "commit" part of the ring buffer data page |
| when returned to be consumed. This was to inform the user space readers that |
| events have been missed, and that the count may be stored at the end of the |
| page. |
| |
| What wasn't handled, was the splice code that actually called a function to |
| return the length of the data in order to zero out the rest of the page |
| before sending it up to user space. These data bits were returned with the |
| length making the value negative, and that negative value was not checked. |
| It was compared to PAGE_SIZE, and only used if the size was less than |
| PAGE_SIZE. Luckily PAGE_SIZE is unsigned long which made the compare an |
| unsigned compare, meaning the negative size value did not end up causing a |
| large portion of memory to be randomly zeroed out. |
| |
| Fixes: 66a8cb95ed040 ("ring-buffer: Add place holder recording of dropped events") |
| Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| kernel/trace/ring_buffer.c | 6 +++++- |
| 1 file changed, 5 insertions(+), 1 deletion(-) |
| |
| --- a/kernel/trace/ring_buffer.c |
| +++ b/kernel/trace/ring_buffer.c |
| @@ -280,6 +280,8 @@ EXPORT_SYMBOL_GPL(ring_buffer_event_data |
| /* Missed count stored at end */ |
| #define RB_MISSED_STORED (1 << 30) |
| |
| +#define RB_MISSED_FLAGS (RB_MISSED_EVENTS|RB_MISSED_STORED) |
| + |
| struct buffer_data_page { |
| u64 time_stamp; /* page time stamp */ |
| local_t commit; /* write committed index */ |
| @@ -331,7 +333,9 @@ static void rb_init_page(struct buffer_d |
| */ |
| size_t ring_buffer_page_len(void *page) |
| { |
| - return local_read(&((struct buffer_data_page *)page)->commit) |
| + struct buffer_data_page *bpage = page; |
| + |
| + return (local_read(&bpage->commit) & ~RB_MISSED_FLAGS) |
| + BUF_PAGE_HDR_SIZE; |
| } |
| |