Messages in this thread Patch in this message | | | From | Barry Song <> | Subject | [PATCH] perf evlist: fix memory corruption for Kernel PMU event | Date | Fri, 2 Oct 2020 00:57:29 +1300 |
| |
Commit 7736627b865d ("perf stat: Use affinity for closing file descriptors") will use FD(evsel, cpu, thread) to read and write file descriptors xyarray. For a kernel PMU event, this leads to serious memory corruption and perf crash. I have seen evlist->core.cpus->nr is 1 while evsel has cpus->nr with the total number of CPUs. so xyarray which is allocated by evlist->core.cpus->nr will get overflow. This leads to various segmentation faults in perf tool for kernel PMU events, eg: ./perf stat -e bus_cycles sleep 1 *** Error in `./perf': free(): invalid next size (fast): 0x00000000401e6370 *** Aborted (core dumped)
Fixes: 7736627b865d ("perf stat: Use affinity for closing file descriptors") Cc: Andi Kleen <ak@linux.intel.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexey Budankov <alexey.budankov@linux.intel.com> Signed-off-by: Barry Song <song.bao.hua@hisilicon.com> --- tools/perf/util/evlist.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index c0768c6..3022152 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -1226,10 +1226,14 @@ void evlist__close(struct evlist *evlist) int cpu, i; /* - * With perf record core.cpus is usually NULL. + * With perf record core.cpus is usually NULL; + * For Kernel PMU event x, "perf stat -e x" will set evlist->core.cpus->nr to + * 1 while evsel has cpus->nr which contains all CPUs. evsel__cpu_iter_skip() + * will be false, memory corruption will happen if we use affinity to close + * file descriptors; * Use the old method to handle this for now. */ - if (!evlist->core.cpus) { + if (!evlist->core.cpus || evlist->core.cpus->nr == 1) { evlist__for_each_entry_reverse(evlist, evsel) evsel__close(evsel); return; -- 2.7.4
| |