summaryrefslogtreecommitdiff
path: root/kernel/events
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2017-08-01 16:09:55 -0700
committerPatrick Fay <pfay@codeaurora.org>2017-08-02 11:10:44 -0700
commit2e54dcd5ed1784bc30fb6b956ed77b7f668acb1f (patch)
tree835155ea8752afaa124f45bde360d175e132b73b /kernel/events
parent9f462e8a2b950650297e36fb77171ac5a7a433a2 (diff)
perf/core: Fix crash in perf_event_read()
Alexei had his box explode because doing read() on a package (rapl/uncore) event that isn't currently scheduled in ends up doing an out-of-bounds load. Rework the code to more explicitly deal with event->oncpu being -1. Author: Peter Zijlstra (Intel) <peterz@infradead.org> Reported-by: Alexei Starovoitov <alexei.starovoitov@gmail.com> Tested-by: Alexei Starovoitov <ast@kernel.org> Tested-by: David Carrillo-Cisneros <davidcc@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: eranian@google.com Fixes: d6a2f9035bfc ("perf/core: Introduce PMU_EV_CAP_READ_ACTIVE_PKG") Signed-off-by: Ingo Molnar <mingo@kernel.org> Git-commit: 451d24d1e5f40bad000fa9abe36ddb16fc9928cb Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [pfay@codeaurora.org: apply the event->oncpu validity check from from the patch. Other code from the patch calls routines not yet in 4.4 so omit that part of patch. This code fixes segfault crashes during reboot where the event->oncpu value is -1. Change-Id: I040f0af2030e53ac3329e4b3a1bbcd37f080cdcf Signed-off-by: Patrick Fay <pfay@codeaurora.org>
Diffstat (limited to 'kernel/events')
-rw-r--r--kernel/events/core.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 7fee87daac56..b54ddbe8b2d1 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3408,22 +3408,27 @@ u64 perf_event_read_local(struct perf_event *event)
static int perf_event_read(struct perf_event *event, bool group)
{
- int ret = 0;
+ int event_cpu, ret = 0;
/*
* If event is enabled and currently active on a CPU, update the
* value in the event structure:
*/
+ event_cpu = READ_ONCE(event->oncpu);
+
if (event->state == PERF_EVENT_STATE_ACTIVE &&
- !cpu_isolated(event->oncpu)) {
+ !cpu_isolated(event_cpu)) {
struct perf_read_data data = {
.event = event,
.group = group,
.ret = 0,
};
+
+ if ((unsigned int)event_cpu >= nr_cpu_ids)
+ return 0;
if (!event->attr.exclude_idle ||
- !per_cpu(is_idle, event->oncpu)) {
- smp_call_function_single(event->oncpu,
+ !per_cpu(is_idle, event_cpu)) {
+ smp_call_function_single(event_cpu,
__perf_event_read, &data, 1);
ret = data.ret;
}