diff options
| author | Frederic Weisbecker <fweisbec@gmail.com> | 2011-05-21 13:33:04 -0400 |
|---|---|---|
| committer | Frederic Weisbecker <fweisbec@gmail.com> | 2011-05-21 21:38:36 -0400 |
| commit | a285412479b6d5af3e48273a92ec2f1987df8cd1 (patch) | |
| tree | 29f68684cebb26b86c3dd0b0f0fc4e5d6553c989 /tools | |
| parent | 74429964d8e29c0107fa6e9cdf35b8f33f57405d (diff) | |
perf tools: Pre-check sample size before parsing
Check that the total size of the sample fields having a fixed
size do not exceed the one of the whole event. This robustifies
the sample parsing.
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Stephane Eranian <eranian@google.com>
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/perf/builtin-test.c | 4 | ||||
| -rw-r--r-- | tools/perf/util/event.c | 16 | ||||
| -rw-r--r-- | tools/perf/util/event.h | 12 | ||||
| -rw-r--r-- | tools/perf/util/evsel.c | 6 | ||||
| -rw-r--r-- | tools/perf/util/python.c | 5 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 1 | ||||
| -rw-r--r-- | tools/perf/util/session.h | 2 |
7 files changed, 41 insertions, 5 deletions
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 11e3c845836..44d7df28043 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c | |||
| @@ -474,6 +474,7 @@ static int test__basic_mmap(void) | |||
| 474 | unsigned int nr_events[nsyscalls], | 474 | unsigned int nr_events[nsyscalls], |
| 475 | expected_nr_events[nsyscalls], i, j; | 475 | expected_nr_events[nsyscalls], i, j; |
| 476 | struct perf_evsel *evsels[nsyscalls], *evsel; | 476 | struct perf_evsel *evsels[nsyscalls], *evsel; |
| 477 | int sample_size = perf_sample_size(attr.sample_type); | ||
| 477 | 478 | ||
| 478 | for (i = 0; i < nsyscalls; ++i) { | 479 | for (i = 0; i < nsyscalls; ++i) { |
| 479 | char name[64]; | 480 | char name[64]; |
| @@ -558,7 +559,8 @@ static int test__basic_mmap(void) | |||
| 558 | goto out_munmap; | 559 | goto out_munmap; |
| 559 | } | 560 | } |
| 560 | 561 | ||
| 561 | perf_event__parse_sample(event, attr.sample_type, false, &sample); | 562 | perf_event__parse_sample(event, attr.sample_type, sample_size, |
| 563 | false, &sample); | ||
| 562 | evsel = perf_evlist__id2evsel(evlist, sample.id); | 564 | evsel = perf_evlist__id2evsel(evlist, sample.id); |
| 563 | if (evsel == NULL) { | 565 | if (evsel == NULL) { |
| 564 | pr_debug("event with id %" PRIu64 | 566 | pr_debug("event with id %" PRIu64 |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 1023f67633a..17c1c3c875c 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
| @@ -35,6 +35,22 @@ const char *perf_event__name(unsigned int id) | |||
| 35 | return perf_event__names[id]; | 35 | return perf_event__names[id]; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | int perf_sample_size(u64 sample_type) | ||
| 39 | { | ||
| 40 | u64 mask = sample_type & PERF_SAMPLE_MASK; | ||
| 41 | int size = 0; | ||
| 42 | int i; | ||
| 43 | |||
| 44 | for (i = 0; i < 64; i++) { | ||
| 45 | if ((mask << i) & 1) | ||
| 46 | size++; | ||
| 47 | } | ||
| 48 | |||
| 49 | size *= sizeof(u64); | ||
| 50 | |||
| 51 | return size; | ||
| 52 | } | ||
| 53 | |||
| 38 | static struct perf_sample synth_sample = { | 54 | static struct perf_sample synth_sample = { |
| 39 | .pid = -1, | 55 | .pid = -1, |
| 40 | .tid = -1, | 56 | .tid = -1, |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 9c35170fb37..c0833287140 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
| @@ -56,6 +56,13 @@ struct read_event { | |||
| 56 | u64 id; | 56 | u64 id; |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | |||
| 60 | #define PERF_SAMPLE_MASK \ | ||
| 61 | (PERF_SAMPLE_IP | PERF_SAMPLE_TID | \ | ||
| 62 | PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | \ | ||
| 63 | PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | \ | ||
| 64 | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD) | ||
| 65 | |||
| 59 | struct sample_event { | 66 | struct sample_event { |
| 60 | struct perf_event_header header; | 67 | struct perf_event_header header; |
| 61 | u64 array[]; | 68 | u64 array[]; |
| @@ -75,6 +82,8 @@ struct perf_sample { | |||
| 75 | struct ip_callchain *callchain; | 82 | struct ip_callchain *callchain; |
| 76 | }; | 83 | }; |
| 77 | 84 | ||
| 85 | int perf_sample_size(u64 sample_type); | ||
| 86 | |||
| 78 | #define BUILD_ID_SIZE 20 | 87 | #define BUILD_ID_SIZE 20 |
| 79 | 88 | ||
| 80 | struct build_id_event { | 89 | struct build_id_event { |
| @@ -178,6 +187,7 @@ int perf_event__preprocess_sample(const union perf_event *self, | |||
| 178 | const char *perf_event__name(unsigned int id); | 187 | const char *perf_event__name(unsigned int id); |
| 179 | 188 | ||
| 180 | int perf_event__parse_sample(const union perf_event *event, u64 type, | 189 | int perf_event__parse_sample(const union perf_event *event, u64 type, |
| 181 | bool sample_id_all, struct perf_sample *sample); | 190 | int sample_size, bool sample_id_all, |
| 191 | struct perf_sample *sample); | ||
| 182 | 192 | ||
| 183 | #endif /* __PERF_RECORD_H */ | 193 | #endif /* __PERF_RECORD_H */ |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index d6fd59beb86..bfce8bf642f 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -304,7 +304,8 @@ static int perf_event__parse_id_sample(const union perf_event *event, u64 type, | |||
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | int perf_event__parse_sample(const union perf_event *event, u64 type, | 306 | int perf_event__parse_sample(const union perf_event *event, u64 type, |
| 307 | bool sample_id_all, struct perf_sample *data) | 307 | int sample_size, bool sample_id_all, |
| 308 | struct perf_sample *data) | ||
| 308 | { | 309 | { |
| 309 | const u64 *array; | 310 | const u64 *array; |
| 310 | 311 | ||
| @@ -319,6 +320,9 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, | |||
| 319 | 320 | ||
| 320 | array = event->sample.array; | 321 | array = event->sample.array; |
| 321 | 322 | ||
| 323 | if (sample_size + sizeof(event->header) > event->header.size) | ||
| 324 | return -EFAULT; | ||
| 325 | |||
| 322 | if (type & PERF_SAMPLE_IP) { | 326 | if (type & PERF_SAMPLE_IP) { |
| 323 | data->ip = event->ip.ip; | 327 | data->ip = event->ip.ip; |
| 324 | array++; | 328 | array++; |
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 8b0eff8b828..4174c099032 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c | |||
| @@ -690,8 +690,9 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, | |||
| 690 | return PyErr_NoMemory(); | 690 | return PyErr_NoMemory(); |
| 691 | 691 | ||
| 692 | first = list_entry(evlist->entries.next, struct perf_evsel, node); | 692 | first = list_entry(evlist->entries.next, struct perf_evsel, node); |
| 693 | perf_event__parse_sample(event, first->attr.sample_type, sample_id_all, | 693 | perf_event__parse_sample(event, first->attr.sample_type, |
| 694 | &pevent->sample); | 694 | perf_sample_size(first->attr.sample_type), |
| 695 | sample_id_all, &pevent->sample); | ||
| 695 | return pyevent; | 696 | return pyevent; |
| 696 | } | 697 | } |
| 697 | 698 | ||
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index db652068c39..8940fd871ea 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -97,6 +97,7 @@ out: | |||
| 97 | void perf_session__update_sample_type(struct perf_session *self) | 97 | void perf_session__update_sample_type(struct perf_session *self) |
| 98 | { | 98 | { |
| 99 | self->sample_type = perf_evlist__sample_type(self->evlist); | 99 | self->sample_type = perf_evlist__sample_type(self->evlist); |
| 100 | self->sample_size = perf_sample_size(self->sample_type); | ||
| 100 | self->sample_id_all = perf_evlist__sample_id_all(self->evlist); | 101 | self->sample_id_all = perf_evlist__sample_id_all(self->evlist); |
| 101 | perf_session__id_header_size(self); | 102 | perf_session__id_header_size(self); |
| 102 | } | 103 | } |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 8daaa2d1539..66d4e149087 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
| @@ -43,6 +43,7 @@ struct perf_session { | |||
| 43 | */ | 43 | */ |
| 44 | struct hists hists; | 44 | struct hists hists; |
| 45 | u64 sample_type; | 45 | u64 sample_type; |
| 46 | int sample_size; | ||
| 46 | int fd; | 47 | int fd; |
| 47 | bool fd_pipe; | 48 | bool fd_pipe; |
| 48 | bool repipe; | 49 | bool repipe; |
| @@ -159,6 +160,7 @@ static inline int perf_session__parse_sample(struct perf_session *session, | |||
| 159 | struct perf_sample *sample) | 160 | struct perf_sample *sample) |
| 160 | { | 161 | { |
| 161 | return perf_event__parse_sample(event, session->sample_type, | 162 | return perf_event__parse_sample(event, session->sample_type, |
| 163 | session->sample_size, | ||
| 162 | session->sample_id_all, sample); | 164 | session->sample_id_all, sample); |
| 163 | } | 165 | } |
| 164 | 166 | ||
