Re: [PATCH] perf synthetic-events: Fix schedstat event lifetime handling
From: Ian Rogers
Date: Tue Sep 15 2026 - 15:41:30 EST
On Fri, Sep 11, 2026 at 10:56 PM Hui Su <sh_def@xxxxxxx> wrote:
>
> 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: c3030995f23b ("perf sched stats: Add record and rawdump support")
> Signed-off-by: Hui Su <sh_def@xxxxxxx>
Reviewed-by: Ian Rogers <irogers@xxxxxxxxxx>
Thanks!
Ian
> ---
> 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 0c150193cca8..2eac2310a01d 100644
> --- a/tools/perf/util/synthetic-events.c
> +++ b/tools/perf/util/synthetic-events.c
> @@ -2817,7 +2817,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;
> @@ -2858,6 +2857,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') {
> @@ -2872,12 +2872,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);
> --
> 2.55.0
>