aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 bfce8bf642f..ee0fe0dffa7 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,
return 0;
}
+static bool sample_overlap(const union perf_event *event,
+ const void *offset, u64 size)
+{
+ const void *base = event;
+
+ if (offset + size > base + event->header.size)
+ return true;
+
+ return false;
+}
+
int perf_event__parse_sample(const union perf_event *event, u64 type,
int sample_size, bool sample_id_all,
struct perf_sample *data)
@@ -373,14 +384,29 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
}
if (type & PERF_SAMPLE_CALLCHAIN) {
+ if (sample_overlap(event, array, sizeof(data->callchain->nr)))
+ return -EFAULT;
+
data->callchain = (struct ip_callchain *)array;
+
+ if (sample_overlap(event, array, data->callchain->nr))
+ return -EFAULT;
+
array += 1 + data->callchain->nr;
}
if (type & PERF_SAMPLE_RAW) {
u32 *p = (u32 *)array;
+
+ if (sample_overlap(event, array, sizeof(u32)))
+ return -EFAULT;
+
data->raw_size = *p;
p++;
+
+ if (sample_overlap(event, p, data->raw_size))
+ return -EFAULT;
+
data->raw_data = p;
}