aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2011-05-21 14:08:15 -0400
committerFrederic Weisbecker <fweisbec@gmail.com>2011-05-21 21:38:48 -0400
commit98e1da905cbe64bb023a165c7c01eef5e800609e (patch)
treec77e7a64263ecb8fc9f7971a44dd085f14f039f6 /tools/perf
parenta285412479b6d5af3e48273a92ec2f1987df8cd1 (diff)
perf tools: Robustify dynamic sample content fetch
Ensure the size of the dynamic fields such as callchains or raw events don't overlap the whole event boundaries. This prevents from dereferencing junk if the given size of the callchain goes too eager. Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Reported-by: Ingo Molnar <mingo@elte.hu> 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/perf')
-rw-r--r--tools/perf/util/evsel.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index bfce8bf642fa..ee0fe0dffa71 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -303,6 +303,17 @@ static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
303 return 0; 303 return 0;
304} 304}
305 305
306static bool sample_overlap(const union perf_event *event,
307 const void *offset, u64 size)
308{
309 const void *base = event;
310
311 if (offset + size > base + event->header.size)
312 return true;
313
314 return false;
315}
316
306int perf_event__parse_sample(const union perf_event *event, u64 type, 317int perf_event__parse_sample(const union perf_event *event, u64 type,
307 int sample_size, bool sample_id_all, 318 int sample_size, bool sample_id_all,
308 struct perf_sample *data) 319 struct perf_sample *data)
@@ -373,14 +384,29 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
373 } 384 }
374 385
375 if (type & PERF_SAMPLE_CALLCHAIN) { 386 if (type & PERF_SAMPLE_CALLCHAIN) {
387 if (sample_overlap(event, array, sizeof(data->callchain->nr)))
388 return -EFAULT;
389
376 data->callchain = (struct ip_callchain *)array; 390 data->callchain = (struct ip_callchain *)array;
391
392 if (sample_overlap(event, array, data->callchain->nr))
393 return -EFAULT;
394
377 array += 1 + data->callchain->nr; 395 array += 1 + data->callchain->nr;
378 } 396 }
379 397
380 if (type & PERF_SAMPLE_RAW) { 398 if (type & PERF_SAMPLE_RAW) {
381 u32 *p = (u32 *)array; 399 u32 *p = (u32 *)array;
400
401 if (sample_overlap(event, array, sizeof(u32)))
402 return -EFAULT;
403
382 data->raw_size = *p; 404 data->raw_size = *p;
383 p++; 405 p++;
406
407 if (sample_overlap(event, p, data->raw_size))
408 return -EFAULT;
409
384 data->raw_data = p; 410 data->raw_data = p;
385 } 411 }
386 412