Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2854124 authored by Frederic Weisbecker's avatar Frederic Weisbecker
Browse files

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: default avatarFrederic 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>
parent 74429964
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -474,6 +474,7 @@ static int test__basic_mmap(void)
	unsigned int nr_events[nsyscalls],
		     expected_nr_events[nsyscalls], i, j;
	struct perf_evsel *evsels[nsyscalls], *evsel;
	int sample_size = perf_sample_size(attr.sample_type);

	for (i = 0; i < nsyscalls; ++i) {
		char name[64];
@@ -558,7 +559,8 @@ static int test__basic_mmap(void)
			goto out_munmap;
		}

		perf_event__parse_sample(event, attr.sample_type, false, &sample);
		perf_event__parse_sample(event, attr.sample_type, sample_size,
					 false, &sample);
		evsel = perf_evlist__id2evsel(evlist, sample.id);
		if (evsel == NULL) {
			pr_debug("event with id %" PRIu64
+16 −0
Original line number Diff line number Diff line
@@ -35,6 +35,22 @@ const char *perf_event__name(unsigned int id)
	return perf_event__names[id];
}

int perf_sample_size(u64 sample_type)
{
	u64 mask = sample_type & PERF_SAMPLE_MASK;
	int size = 0;
	int i;

	for (i = 0; i < 64; i++) {
		if ((mask << i) & 1)
			size++;
	}

	size *= sizeof(u64);

	return size;
}

static struct perf_sample synth_sample = {
	.pid	   = -1,
	.tid	   = -1,
+11 −1
Original line number Diff line number Diff line
@@ -56,6 +56,13 @@ struct read_event {
	u64 id;
};


#define PERF_SAMPLE_MASK				\
	(PERF_SAMPLE_IP | PERF_SAMPLE_TID |		\
	 PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR |		\
	PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID |	\
	 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)

struct sample_event {
	struct perf_event_header        header;
	u64 array[];
@@ -75,6 +82,8 @@ struct perf_sample {
	struct ip_callchain *callchain;
};

int perf_sample_size(u64 sample_type);

#define BUILD_ID_SIZE 20

struct build_id_event {
@@ -178,6 +187,7 @@ int perf_event__preprocess_sample(const union perf_event *self,
const char *perf_event__name(unsigned int id);

int perf_event__parse_sample(const union perf_event *event, u64 type,
			     bool sample_id_all, struct perf_sample *sample);
			     int sample_size, bool sample_id_all,
			     struct perf_sample *sample);

#endif /* __PERF_RECORD_H */
+5 −1
Original line number Diff line number Diff line
@@ -304,7 +304,8 @@ static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
}

int perf_event__parse_sample(const union perf_event *event, u64 type,
			     bool sample_id_all, struct perf_sample *data)
			     int sample_size, bool sample_id_all,
			     struct perf_sample *data)
{
	const u64 *array;

@@ -319,6 +320,9 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,

	array = event->sample.array;

	if (sample_size + sizeof(event->header) > event->header.size)
		return -EFAULT;

	if (type & PERF_SAMPLE_IP) {
		data->ip = event->ip.ip;
		array++;
+3 −2
Original line number Diff line number Diff line
@@ -690,8 +690,9 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
			return PyErr_NoMemory();

		first = list_entry(evlist->entries.next, struct perf_evsel, node);
		perf_event__parse_sample(event, first->attr.sample_type, sample_id_all,
					 &pevent->sample);
		perf_event__parse_sample(event, first->attr.sample_type,
					 perf_sample_size(first->attr.sample_type),
					 sample_id_all, &pevent->sample);
		return pyevent;
	}

Loading