From: Ian Rogers <irogers@xxxxxxxxxx> [ Upstream commit 797b9ec8c4bc9ec89f633a9b2c710b7b64753ca4 ] Address/memory sanitizer was reporting issues in evsel__group_pmu_name because the for_each_group_evsel loop didn't terminate when the head was reached, the head would then be cast and accessed as an evsel leading to invalid memory accesses. Fix for_each_group_member and for_each_group_evsel to terminate at the list head. Note, evsel__group_pmu_name no longer iterates the group, but the problem is present regardless. Fixes: 717e263fc354d53d ("perf report: Show group description when event group is enabled") Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx> Cc: Adrian Hunter <adrian.hunter@xxxxxxxxx> Cc: Alexander Shishkin <alexander.shishkin@xxxxxxxxxxxxxxx> Cc: Changbin Du <changbin.du@xxxxxxxxxx> Cc: Dmitrii Dolgov <9erthalion6@xxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxxxxx> Cc: James Clark <james.clark@xxxxxxx> Cc: Jiri Olsa <jolsa@xxxxxxxxxx> Cc: Kan Liang <kan.liang@xxxxxxxxxxxxxxx> Cc: Mark Rutland <mark.rutland@xxxxxxx> Cc: Namhyung Kim <namhyung.kim@xxxxxxx> Cc: Namhyung Kim <namhyung@xxxxxxxxxx> Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx> Cc: Rob Herring <robh@xxxxxxxxxx> Cc: Sandipan Das <sandipan.das@xxxxxxx> Cc: Xing Zhengjun <zhengjun.xing@xxxxxxxxxxxxxxx> Link: https://lore.kernel.org/r/20230526194442.2355872-3-irogers@xxxxxxxxxx Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx> Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> --- tools/perf/util/evsel.h | 24 ++++++++++++++++-------- tools/perf/util/evsel_fprintf.c | 1 + 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 1a7358b46ad4e..72549fd79992b 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -457,16 +457,24 @@ static inline int evsel__group_idx(struct evsel *evsel) } /* Iterates group WITHOUT the leader. */ -#define for_each_group_member(_evsel, _leader) \ -for ((_evsel) = list_entry((_leader)->core.node.next, struct evsel, core.node); \ - (_evsel) && (_evsel)->core.leader == (&_leader->core); \ - (_evsel) = list_entry((_evsel)->core.node.next, struct evsel, core.node)) +#define for_each_group_member_head(_evsel, _leader, _head) \ +for ((_evsel) = list_entry((_leader)->core.node.next, struct evsel, core.node); \ + (_evsel) && &(_evsel)->core.node != (_head) && \ + (_evsel)->core.leader == &(_leader)->core; \ + (_evsel) = list_entry((_evsel)->core.node.next, struct evsel, core.node)) + +#define for_each_group_member(_evsel, _leader) \ + for_each_group_member_head(_evsel, _leader, &(_leader)->evlist->core.entries) /* Iterates group WITH the leader. */ -#define for_each_group_evsel(_evsel, _leader) \ -for ((_evsel) = _leader; \ - (_evsel) && (_evsel)->core.leader == (&_leader->core); \ - (_evsel) = list_entry((_evsel)->core.node.next, struct evsel, core.node)) +#define for_each_group_evsel_head(_evsel, _leader, _head) \ +for ((_evsel) = _leader; \ + (_evsel) && &(_evsel)->core.node != (_head) && \ + (_evsel)->core.leader == &(_leader)->core; \ + (_evsel) = list_entry((_evsel)->core.node.next, struct evsel, core.node)) + +#define for_each_group_evsel(_evsel, _leader) \ + for_each_group_evsel_head(_evsel, _leader, &(_leader)->evlist->core.entries) static inline bool evsel__has_branch_callstack(const struct evsel *evsel) { diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c index bd22c4932d10e..6fa3a306f301d 100644 --- a/tools/perf/util/evsel_fprintf.c +++ b/tools/perf/util/evsel_fprintf.c @@ -2,6 +2,7 @@ #include <inttypes.h> #include <stdio.h> #include <stdbool.h> +#include "util/evlist.h" #include "evsel.h" #include "util/evsel_fprintf.h" #include "util/event.h" -- 2.39.2