diff options
Diffstat (limited to 'tools/perf/util/evsel.c')
-rw-r--r-- | tools/perf/util/evsel.c | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index d6fd59beb860..ee0fe0dffa71 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -303,8 +303,20 @@ static int perf_event__parse_id_sample(const union perf_event *event, u64 type, | |||
303 | return 0; | 303 | return 0; |
304 | } | 304 | } |
305 | 305 | ||
306 | static 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 | |||
306 | int perf_event__parse_sample(const union perf_event *event, u64 type, | 317 | int perf_event__parse_sample(const union perf_event *event, u64 type, |
307 | bool sample_id_all, struct perf_sample *data) | 318 | int sample_size, bool sample_id_all, |
319 | struct perf_sample *data) | ||
308 | { | 320 | { |
309 | const u64 *array; | 321 | const u64 *array; |
310 | 322 | ||
@@ -319,6 +331,9 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, | |||
319 | 331 | ||
320 | array = event->sample.array; | 332 | array = event->sample.array; |
321 | 333 | ||
334 | if (sample_size + sizeof(event->header) > event->header.size) | ||
335 | return -EFAULT; | ||
336 | |||
322 | if (type & PERF_SAMPLE_IP) { | 337 | if (type & PERF_SAMPLE_IP) { |
323 | data->ip = event->ip.ip; | 338 | data->ip = event->ip.ip; |
324 | array++; | 339 | array++; |
@@ -369,14 +384,29 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, | |||
369 | } | 384 | } |
370 | 385 | ||
371 | 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 | |||
372 | 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 | |||
373 | array += 1 + data->callchain->nr; | 395 | array += 1 + data->callchain->nr; |
374 | } | 396 | } |
375 | 397 | ||
376 | if (type & PERF_SAMPLE_RAW) { | 398 | if (type & PERF_SAMPLE_RAW) { |
377 | u32 *p = (u32 *)array; | 399 | u32 *p = (u32 *)array; |
400 | |||
401 | if (sample_overlap(event, array, sizeof(u32))) | ||
402 | return -EFAULT; | ||
403 | |||
378 | data->raw_size = *p; | 404 | data->raw_size = *p; |
379 | p++; | 405 | p++; |
406 | |||
407 | if (sample_overlap(event, p, data->raw_size)) | ||
408 | return -EFAULT; | ||
409 | |||
380 | data->raw_data = p; | 410 | data->raw_data = p; |
381 | } | 411 | } |
382 | 412 | ||