Messages in this thread | | | Date | Thu, 17 Nov 2022 16:40:03 -0500 | From | Steven Rostedt <> | Subject | Re: [PATCH] tracing: Fix infinite loop in tracing_read_pipe on overflowed print_trace_line |
| |
On Mon, 14 Nov 2022 10:29:46 +0800 Yang Jihong <yangjihong1@huawei.com> wrote:
> print_trace_line may overflow seq_file buffer. If the event is not > consumed, the while loop keeps peeking this event, causing a infinite loop. > > Signed-off-by: Yang Jihong <yangjihong1@huawei.com> > --- > kernel/trace/trace.c | 13 +++++++++++++ > 1 file changed, 13 insertions(+) > > diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c > index 47a44b055a1d..2a8d5c68c29b 100644 > --- a/kernel/trace/trace.c > +++ b/kernel/trace/trace.c > @@ -6788,6 +6788,19 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, > if (ret == TRACE_TYPE_PARTIAL_LINE) { > /* don't print partial lines */ > iter->seq.seq.len = save_len; > + > + /* > + * If one trace_line of the tracer overflows seq_file > + * buffer, trace_seq_to_user returns -EBUSY because > + * nothing in the sequence (iter->seq.seq.len = \ > + * iter->seq.seq.readpos = 0). > + * In this case, we need to consume, otherwise, > + * "while" will peek this event next time, resulting > + * in an infinite loop. > + */ > + if (trace_seq_has_overflowed(&iter->seq)) > + trace_consume(iter);
Instead of consuming it, I think the right solution is to print the partial line. Something like:
if (trace_seq_has_overflowed(&iter->seq)) { char dots[] = "...";
iter->seq.seq.len -= sizeof(dots) + 1; iter->seq.seq.full = 0; trace_seq_puts(&iter->seq, dots); trace_consume(iter); break; }
iter->seq.seq.len = save_len; break;
That way we can see the broken trace event and not just silently drop it.
-- Steve
> + > break; > } > if (ret != TRACE_TYPE_NO_CONSUME)
| |