aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2011-05-21 13:33:04 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2011-05-21 21:38:36 -0400
commita285412479b6d5af3e48273a92ec2f1987df8cd1 (patch)
tree29f68684cebb26b86c3dd0b0f0fc4e5d6553c989
parent74429964d8e29c0107fa6e9cdf35b8f33f57405d (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>
-rw-r--r--tools/perf/builtin-test.c4
-rw-r--r--tools/perf/util/event.c16
-rw-r--r--tools/perf/util/event.h12
-rw-r--r--tools/perf/util/evsel.c6
-rw-r--r--tools/perf/util/python.c5
-rw-r--r--tools/perf/util/session.c1
-rw-r--r--tools/perf/util/session.h2
7 files changed, 41 insertions, 5 deletions
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 11e3c8458362..44d7df280430 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 1023f67633a4..17c1c3c875c3 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
38int 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
38static struct perf_sample synth_sample = { 54static 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 9c35170fb379..c08332871408 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
59struct sample_event { 66struct 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
85int perf_sample_size(u64 sample_type);
86
78#define BUILD_ID_SIZE 20 87#define BUILD_ID_SIZE 20
79 88
80struct build_id_event { 89struct build_id_event {
@@ -178,6 +187,7 @@ int perf_event__preprocess_sample(const union perf_event *self,
178const char *perf_event__name(unsigned int id); 187const char *perf_event__name(unsigned int id);
179 188
180int perf_event__parse_sample(const union perf_event *event, u64 type, 189int 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 d6fd59beb860..bfce8bf642fa 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
306int perf_event__parse_sample(const union perf_event *event, u64 type, 306int 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 8b0eff8b8283..4174c0990320 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 db652068c396..8940fd871eae 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -97,6 +97,7 @@ out:
97void perf_session__update_sample_type(struct perf_session *self) 97void 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 8daaa2d15396..66d4e1490879 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