Skip to content

Commit e1e3592

Browse files
David Sharprostedt
authored andcommitted
ring_buffer: Off-by-one and duplicate events in ring_buffer_read_page
Fix two related problems in the event-copying loop of ring_buffer_read_page. The loop condition for copying events is off-by-one. "len" is the remaining space in the caller-supplied page. "size" is the size of the next event (or two events). If len == size, then there is just enough space for the next event. size was set to rb_event_ts_length, which may include the size of two events if the first event is a time-extend, in order to assure time- extends are kept together with the event after it. However, rb_advance_reader always advances by one event. This would result in the event after any time-extend being duplicated. Instead, get the size of a single event for the memcpy, but use rb_event_ts_length for the loop condition. Signed-off-by: David Sharp <[email protected]> LKML-Reference: <[email protected]> LKML-Reference: <[email protected]> Signed-off-by: Steven Rostedt <[email protected]>
1 parent 2ce494a commit e1e3592

File tree

1 file changed

+8
-1
lines changed

1 file changed

+8
-1
lines changed

kernel/trace/ring_buffer.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3853,6 +3853,13 @@ int ring_buffer_read_page(struct ring_buffer *buffer,
38533853

38543854
/* Need to copy one event at a time */
38553855
do {
3856+
/* We need the size of one event, because
3857+
* rb_advance_reader only advances by one event,
3858+
* whereas rb_event_ts_length may include the size of
3859+
* one or two events.
3860+
* We have already ensured there's enough space if this
3861+
* is a time extend. */
3862+
size = rb_event_length(event);
38563863
memcpy(bpage->data + pos, rpage->data + rpos, size);
38573864

38583865
len -= size;
@@ -3867,7 +3874,7 @@ int ring_buffer_read_page(struct ring_buffer *buffer,
38673874
event = rb_reader_event(cpu_buffer);
38683875
/* Always keep the time extend and data together */
38693876
size = rb_event_ts_length(event);
3870-
} while (len > size);
3877+
} while (len >= size);
38713878

38723879
/* update bpage */
38733880
local_set(&bpage->commit, pos);

0 commit comments

Comments
 (0)