From: Ian Rogers irogers@google.com
[ 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@google.com Cc: Adrian Hunter adrian.hunter@intel.com Cc: Alexander Shishkin alexander.shishkin@linux.intel.com Cc: Changbin Du changbin.du@huawei.com Cc: Dmitrii Dolgov 9erthalion6@gmail.com Cc: Ingo Molnar mingo@redhat.com Cc: James Clark james.clark@arm.com Cc: Jiri Olsa jolsa@kernel.org Cc: Kan Liang kan.liang@linux.intel.com Cc: Mark Rutland mark.rutland@arm.com Cc: Namhyung Kim namhyung.kim@lge.com Cc: Namhyung Kim namhyung@kernel.org Cc: Peter Zijlstra peterz@infradead.org Cc: Rob Herring robh@kernel.org Cc: Sandipan Das sandipan.das@amd.com Cc: Xing Zhengjun zhengjun.xing@linux.intel.com Link: https://lore.kernel.org/r/20230526194442.2355872-3-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo acme@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org --- 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"