diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2015-05-19 09:05:45 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-05-27 11:21:43 -0400 |
commit | 554e92ed8fcdbcad736ef906c393847d44d52692 (patch) | |
tree | a614aa7e175aad3f5e36540e03bbd7e9c1df5dcd /tools/perf/util/session.c | |
parent | 05b41775e2edd69a83f592e3534930c934d4038e (diff) |
perf session: Fix perf_session__peek_event()
perf_session__peek_event() generally leverages there being a single mmap
of the perf.data file, however on 32-bit platforms when there is more
that 32MiB of data, then there are multiple mmaps, so
perf_session__peek_event() reads from the file.
In that case a couple of bugs were exposed (note how the seg. fault
appears with >32M of data):
$ perf record --per-thread -e intel_bts// ../rtit-tests/loopy 1000000
[ perf record: Woken up 13 times to write data ]
[ perf record: Captured and wrote 24.568 MB perf.data ]
$ perf script > /dev/null
$ perf record --per-thread -e intel_bts// ../rtit-tests/loopy 10000000
[ perf record: Woken up 136 times to write data ]
[ perf record: Captured and wrote 270.794 MB perf.data ]
$ perf script > /dev/null
Segmentation fault (core dumped)
The wrong address was being passed to the readn() function and the
buffer size was not being checked.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung@gmail.com>
Link: http://lkml.kernel.org/r/1432040746-1755-5-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r-- | tools/perf/util/session.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index e722107f932a..39fe09d5a87e 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -1182,7 +1182,7 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset, | |||
1182 | return -1; | 1182 | return -1; |
1183 | 1183 | ||
1184 | if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 || | 1184 | if (lseek(fd, file_offset, SEEK_SET) == (off_t)-1 || |
1185 | readn(fd, &buf, hdr_sz) != (ssize_t)hdr_sz) | 1185 | readn(fd, buf, hdr_sz) != (ssize_t)hdr_sz) |
1186 | return -1; | 1186 | return -1; |
1187 | 1187 | ||
1188 | event = (union perf_event *)buf; | 1188 | event = (union perf_event *)buf; |
@@ -1190,12 +1190,12 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset, | |||
1190 | if (session->header.needs_swap) | 1190 | if (session->header.needs_swap) |
1191 | perf_event_header__bswap(&event->header); | 1191 | perf_event_header__bswap(&event->header); |
1192 | 1192 | ||
1193 | if (event->header.size < hdr_sz) | 1193 | if (event->header.size < hdr_sz || event->header.size > buf_sz) |
1194 | return -1; | 1194 | return -1; |
1195 | 1195 | ||
1196 | rest = event->header.size - hdr_sz; | 1196 | rest = event->header.size - hdr_sz; |
1197 | 1197 | ||
1198 | if (readn(fd, &buf, rest) != (ssize_t)rest) | 1198 | if (readn(fd, buf, rest) != (ssize_t)rest) |
1199 | return -1; | 1199 | return -1; |
1200 | 1200 | ||
1201 | if (session->header.needs_swap) | 1201 | if (session->header.needs_swap) |