aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Rogers <[email protected]>2023-05-26 12:44:42 -0700
committerArnaldo Carvalho de Melo <[email protected]>2023-05-28 10:17:36 -0300
commit797b9ec8c4bc9ec89f633a9b2c710b7b64753ca4 (patch)
tree7f13671a5e26a83cb880515cba474b91a37efce1
parenta90cc5a9eeab45eaf9e47740366b8cf98c3aeb83 (diff)
perf evsel: Don't let for_each_group() treat the head of the list as one of its nodes
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 <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Changbin Du <[email protected]> Cc: Dmitrii Dolgov <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: James Clark <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Kan Liang <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Rob Herring <[email protected]> Cc: Sandipan Das <[email protected]> Cc: Xing Zhengjun <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
-rw-r--r--tools/perf/util/evsel.h24
-rw-r--r--tools/perf/util/evsel_fprintf.c1
2 files changed, 17 insertions, 8 deletions
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 6d9536ecbc7b..5e8371613565 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -459,16 +459,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 79e42d66f55b..a1655fd7ed9b 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"