| From a668cc07f990d2ed19424d5c1a529521a9d1cee1 Mon Sep 17 00:00:00 2001 |
| From: Adrian Hunter <adrian.hunter@intel.com> |
| Date: Wed, 13 Apr 2022 14:42:32 +0300 |
| Subject: perf tools: Fix segfault accessing sample_id xyarray |
| |
| From: Adrian Hunter <adrian.hunter@intel.com> |
| |
| commit a668cc07f990d2ed19424d5c1a529521a9d1cee1 upstream. |
| |
| perf_evsel::sample_id is an xyarray which can cause a segfault when |
| accessed beyond its size. e.g. |
| |
| # perf record -e intel_pt// -C 1 sleep 1 |
| Segmentation fault (core dumped) |
| # |
| |
| That is happening because a dummy event is opened to capture text poke |
| events accross all CPUs, however the mmap logic is allocating according |
| to the number of user_requested_cpus. |
| |
| In general, perf sometimes uses the evsel cpus to open events, and |
| sometimes the evlist user_requested_cpus. However, it is not necessary |
| to determine which case is which because the opened event file |
| descriptors are also in an xyarray, the size of whch can be used |
| to correctly allocate the size of the sample_id xyarray, because there |
| is one ID per file descriptor. |
| |
| Note, in the affected code path, perf_evsel fd array is subsequently |
| used to get the file descriptor for the mmap, so it makes sense for the |
| xyarrays to be the same size there. |
| |
| Fixes: d1a177595b3a824c ("libperf: Adopt perf_evlist__mmap()/munmap() from tools/perf") |
| Fixes: 246eba8e9041c477 ("perf tools: Add support for PERF_RECORD_TEXT_POKE") |
| Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> |
| Acked-by: Ian Rogers <irogers@google.com> |
| Cc: Adrian Hunter <adrian.hunter@intel.com> |
| Cc: Jiri Olsa <jolsa@kernel.org> |
| Cc: stable@vger.kernel.org # 5.5+ |
| Link: https://lore.kernel.org/r/20220413114232.26914-1-adrian.hunter@intel.com |
| Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| tools/lib/perf/evlist.c | 3 +-- |
| 1 file changed, 1 insertion(+), 2 deletions(-) |
| |
| --- a/tools/lib/perf/evlist.c |
| +++ b/tools/lib/perf/evlist.c |
| @@ -571,7 +571,6 @@ int perf_evlist__mmap_ops(struct perf_ev |
| { |
| struct perf_evsel *evsel; |
| const struct perf_cpu_map *cpus = evlist->cpus; |
| - const struct perf_thread_map *threads = evlist->threads; |
| |
| if (!ops || !ops->get || !ops->mmap) |
| return -EINVAL; |
| @@ -583,7 +582,7 @@ int perf_evlist__mmap_ops(struct perf_ev |
| perf_evlist__for_each_entry(evlist, evsel) { |
| if ((evsel->attr.read_format & PERF_FORMAT_ID) && |
| evsel->sample_id == NULL && |
| - perf_evsel__alloc_id(evsel, perf_cpu_map__nr(cpus), threads->nr) < 0) |
| + perf_evsel__alloc_id(evsel, evsel->fd->max_x, evsel->fd->max_y) < 0) |
| return -ENOMEM; |
| } |
| |