|
@@ -303,6 +303,17 @@ static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
|
|
return 0;
|
|
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 perf_event__parse_sample(const union perf_event *event, u64 type,
|
|
int sample_size, bool sample_id_all,
|
|
int sample_size, bool sample_id_all,
|
|
struct perf_sample *data)
|
|
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 (type & PERF_SAMPLE_CALLCHAIN) {
|
|
|
|
+ if (sample_overlap(event, array, sizeof(data->callchain->nr)))
|
|
|
|
+ return -EFAULT;
|
|
|
|
+
|
|
data->callchain = (struct ip_callchain *)array;
|
|
data->callchain = (struct ip_callchain *)array;
|
|
|
|
+
|
|
|
|
+ if (sample_overlap(event, array, data->callchain->nr))
|
|
|
|
+ return -EFAULT;
|
|
|
|
+
|
|
array += 1 + data->callchain->nr;
|
|
array += 1 + data->callchain->nr;
|
|
}
|
|
}
|
|
|
|
|
|
if (type & PERF_SAMPLE_RAW) {
|
|
if (type & PERF_SAMPLE_RAW) {
|
|
u32 *p = (u32 *)array;
|
|
u32 *p = (u32 *)array;
|
|
|
|
+
|
|
|
|
+ if (sample_overlap(event, array, sizeof(u32)))
|
|
|
|
+ return -EFAULT;
|
|
|
|
+
|
|
data->raw_size = *p;
|
|
data->raw_size = *p;
|
|
p++;
|
|
p++;
|
|
|
|
+
|
|
|
|
+ if (sample_overlap(event, p, data->raw_size))
|
|
|
|
+ return -EFAULT;
|
|
|
|
+
|
|
data->raw_data = p;
|
|
data->raw_data = p;
|
|
}
|
|
}
|
|
|
|
|