Messages in this thread Patch in this message | | | From | Nikita Yushchenko <> | Subject | [PATCH] tracing: fix va_list breakage in trace_check_vprintf() | Date | Wed, 17 Nov 2021 21:37:20 +0300 |
| |
When trace_check_vprintf() extracts parts of the format string and passes those to trace_seq_printf() together with va_list, it expects that trace_seq_printf() consumes arguments from va_list, as defined by the passed format substring.
However, trace_seq_printf() has a special path for overflow handling, that does not consume any arguments from va_list. This causes va_list to get out of sync with format string processing, the next va_arg() inside trace_check_vprintf() gets wrong argument, and WARN_ON_ONCE() hits.
This situation easily triggers by ftrace_stress_test from LTP.
Fix that by adding a dummy vsnprintf() call to the overflow path inside trace_seq_printf() to ensure args from va_list are still consumed.
Signed-off-by: Nikita Yushchenko <nikita.yushchenko@virtuozzo.com> --- kernel/trace/trace_seq.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/kernel/trace/trace_seq.c b/kernel/trace/trace_seq.c index 9c90b3a7dce2..3551b5e18aa2 100644 --- a/kernel/trace/trace_seq.c +++ b/kernel/trace/trace_seq.c @@ -141,9 +141,15 @@ EXPORT_SYMBOL_GPL(trace_seq_bitmask); void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) { unsigned int save_len = s->seq.len; + char buf[1]; - if (s->full) + if (s->full) { + /* Consume args from va_list before returning, some callers + * expect that. + */ + vsnprintf(buf, sizeof(buf), fmt, args); return; + } __trace_seq_init(s); -- 2.30.2
| |