From cf3d239189da0bd5122ae38c62f5fefdb744eb86 Mon Sep 17 00:00:00 2001 From: Hui Su Date: Sat, 12 Sep 2026 14:56:19 +0900 Subject: [PATCH] perf synthetic-events: Fix schedstat event lifetime handling perf_event__synthesize_schedstat() has two event lifetime issues. After a successful iteration, event is freed but retains its value. If the next iteration starts with an unrecognized schedstat record type, neither synthesizer assigns a new value. The stale pointer then passes the NULL check, may be passed to process(), and is freed again. In addition, when user_requested_cpus filters out a synthesized event, the continue path skips free(event), leaking the event. Make event local to each loop iteration so it always starts as NULL. Also avoid the filter continue and unconditionally free each synthesized event at the end of the iteration. Fixes: c3030995f23b3d35 ("perf sched stats: Add record and rawdump support") Reviewed-by: Ian Rogers Signed-off-by: Hui Su Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/synthetic-events.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c index 6c5e2327fdfa..44eff2391539 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -2855,7 +2855,6 @@ int perf_event__synthesize_schedstat(const struct perf_tool *tool, struct perf_cpu_map *user_requested_cpus) { char *line = NULL, path[PATH_MAX]; - union perf_event *event = NULL; size_t line_len = 0; char bf[BUFSIZ]; __u64 timestamp; @@ -2896,6 +2895,7 @@ int perf_event__synthesize_schedstat(const struct perf_tool *tool, * for filtered out cpus. */ for (ch = io__get_char(&io); !io.eof; ch = io__get_char(&io)) { + union perf_event *event = NULL; struct perf_cpu this_cpu; if (ch == 'c') { @@ -2910,12 +2910,12 @@ int perf_event__synthesize_schedstat(const struct perf_tool *tool, this_cpu.cpu = cpu; - if (user_requested_cpus && !perf_cpu_map__has(user_requested_cpus, this_cpu)) - continue; - - if (process(tool, event, NULL, NULL) < 0) { - free(event); - goto out_free_line; + if (!user_requested_cpus || + perf_cpu_map__has(user_requested_cpus, this_cpu)) { + if (process(tool, event, NULL, NULL) < 0) { + free(event); + goto out_free_line; + } } free(event);