Revert "perf: Fix perf_event_validate_size()"
This reverts commit 152f51d159
which is
commit 382c27f4ed28f803b1f1473ac2d8db0afc795a1b upstream.
It breaks the Android kernel abi and can be brought back in the future
in an abi-safe way if it is really needed.
Bug: 161946584
Change-Id: I7db90bfbe74a408b807480c811382e38731f0c53
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
parent
5c9845d8c6
commit
8eb4011508
@ -1711,34 +1711,31 @@ static inline void perf_event__state_init(struct perf_event *event)
|
|||||||
PERF_EVENT_STATE_INACTIVE;
|
PERF_EVENT_STATE_INACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __perf_event_read_size(u64 read_format, int nr_siblings)
|
static void __perf_event_read_size(struct perf_event *event, int nr_siblings)
|
||||||
{
|
{
|
||||||
int entry = sizeof(u64); /* value */
|
int entry = sizeof(u64); /* value */
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int nr = 1;
|
int nr = 1;
|
||||||
|
|
||||||
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
|
if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
|
||||||
size += sizeof(u64);
|
size += sizeof(u64);
|
||||||
|
|
||||||
if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
|
if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
|
||||||
size += sizeof(u64);
|
size += sizeof(u64);
|
||||||
|
|
||||||
if (read_format & PERF_FORMAT_ID)
|
if (event->attr.read_format & PERF_FORMAT_ID)
|
||||||
entry += sizeof(u64);
|
entry += sizeof(u64);
|
||||||
|
|
||||||
if (read_format & PERF_FORMAT_LOST)
|
if (event->attr.read_format & PERF_FORMAT_LOST)
|
||||||
entry += sizeof(u64);
|
entry += sizeof(u64);
|
||||||
|
|
||||||
if (read_format & PERF_FORMAT_GROUP) {
|
if (event->attr.read_format & PERF_FORMAT_GROUP) {
|
||||||
nr += nr_siblings;
|
nr += nr_siblings;
|
||||||
size += sizeof(u64);
|
size += sizeof(u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
size += entry * nr;
|
||||||
* Since perf_event_validate_size() limits this to 16k and inhibits
|
event->read_size = size;
|
||||||
* adding more siblings, this will never overflow.
|
|
||||||
*/
|
|
||||||
return size + nr * entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
|
static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
|
||||||
@ -1779,9 +1776,8 @@ static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
|
|||||||
*/
|
*/
|
||||||
static void perf_event__header_size(struct perf_event *event)
|
static void perf_event__header_size(struct perf_event *event)
|
||||||
{
|
{
|
||||||
event->read_size =
|
__perf_event_read_size(event,
|
||||||
__perf_event_read_size(event->attr.read_format,
|
event->group_leader->nr_siblings);
|
||||||
event->group_leader->nr_siblings);
|
|
||||||
__perf_event_header_size(event, event->attr.sample_type);
|
__perf_event_header_size(event, event->attr.sample_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1812,35 +1808,24 @@ static void perf_event__id_header_size(struct perf_event *event)
|
|||||||
event->id_header_size = size;
|
event->id_header_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Check that adding an event to the group does not result in anybody
|
|
||||||
* overflowing the 64k event limit imposed by the output buffer.
|
|
||||||
*
|
|
||||||
* Specifically, check that the read_size for the event does not exceed 16k,
|
|
||||||
* read_size being the one term that grows with groups size. Since read_size
|
|
||||||
* depends on per-event read_format, also (re)check the existing events.
|
|
||||||
*
|
|
||||||
* This leaves 48k for the constant size fields and things like callchains,
|
|
||||||
* branch stacks and register sets.
|
|
||||||
*/
|
|
||||||
static bool perf_event_validate_size(struct perf_event *event)
|
static bool perf_event_validate_size(struct perf_event *event)
|
||||||
{
|
{
|
||||||
struct perf_event *sibling, *group_leader = event->group_leader;
|
/*
|
||||||
|
* The values computed here will be over-written when we actually
|
||||||
|
* attach the event.
|
||||||
|
*/
|
||||||
|
__perf_event_read_size(event, event->group_leader->nr_siblings + 1);
|
||||||
|
__perf_event_header_size(event, event->attr.sample_type & ~PERF_SAMPLE_READ);
|
||||||
|
perf_event__id_header_size(event);
|
||||||
|
|
||||||
if (__perf_event_read_size(event->attr.read_format,
|
/*
|
||||||
group_leader->nr_siblings + 1) > 16*1024)
|
* Sum the lot; should not exceed the 64k limit we have on records.
|
||||||
|
* Conservative limit to allow for callchains and other variable fields.
|
||||||
|
*/
|
||||||
|
if (event->read_size + event->header_size +
|
||||||
|
event->id_header_size + sizeof(struct perf_event_header) >= 16*1024)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (__perf_event_read_size(group_leader->attr.read_format,
|
|
||||||
group_leader->nr_siblings + 1) > 16*1024)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for_each_sibling_event(sibling, group_leader) {
|
|
||||||
if (__perf_event_read_size(sibling->attr.read_format,
|
|
||||||
group_leader->nr_siblings + 1) > 16*1024)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user