[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <lsq.1510009387.471407791@decadent.org.uk>
Date: Mon, 06 Nov 2017 23:03:07 +0000
From: Ben Hutchings <ben@...adent.org.uk>
To: linux-kernel@...r.kernel.org, stable@...r.kernel.org
CC: akpm@...ux-foundation.org,
"Peter Zijlstra" <a.p.zijlstra@...llo.nl>,
"Alexander Shishkin" <alexander.shishkin@...ux.intel.com>,
"Thomas Gleixner" <tglx@...utronix.de>,
"Peter Zijlstra (Intel)" <peterz@...radead.org>,
"Arnaldo Carvalho de Melo" <acme@...hat.com>,
"Jiri Olsa" <jolsa@...hat.com>, "Andi Kleen" <ak@...ux.intel.com>,
"Jiri Olsa" <jolsa@...nel.org>,
"Linus Torvalds" <torvalds@...ux-foundation.org>,
"Ingo Molnar" <mingo@...nel.org>
Subject: [PATCH 3.2 018/147] perf/core: Fix locking for children siblings
group read
3.2.95-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Olsa <jolsa@...nel.org>
commit 2aeb1883547626d82c597cce2c99f0b9c62e2425 upstream.
We're missing ctx lock when iterating children siblings
within the perf_read path for group reading. Following
race and crash can happen:
User space doing read syscall on event group leader:
T1:
perf_read
lock event->ctx->mutex
perf_read_group
lock leader->child_mutex
__perf_read_group_add(child)
list_for_each_entry(sub, &leader->sibling_list, group_entry)
----> sub might be invalid at this point, because it could
get removed via perf_event_exit_task_context in T2
Child exiting and cleaning up its events:
T2:
perf_event_exit_task_context
lock ctx->mutex
list_for_each_entry_safe(child_event, next, &child_ctx->event_list,...
perf_event_exit_event(child)
lock ctx->lock
perf_group_detach(child)
unlock ctx->lock
----> child is removed from sibling_list without any sync
with T1 path above
...
free_event(child)
Before the child is removed from the leader's child_list,
(and thus is omitted from perf_read_group processing), we
need to ensure that perf_read_group touches child's
siblings under its ctx->lock.
Peter further notes:
| One additional note; this bug got exposed by commit:
|
| ba5213ae6b88 ("perf/core: Correct event creation with PERF_FORMAT_GROUP")
|
| which made it possible to actually trigger this code-path.
Tested-by: Andi Kleen <ak@...ux.intel.com>
Signed-off-by: Jiri Olsa <jolsa@...nel.org>
Acked-by: Peter Zijlstra (Intel) <peterz@...radead.org>
Cc: Alexander Shishkin <alexander.shishkin@...ux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@...hat.com>
Cc: Jiri Olsa <jolsa@...hat.com>
Cc: Linus Torvalds <torvalds@...ux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@...llo.nl>
Cc: Peter Zijlstra <peterz@...radead.org>
Cc: Thomas Gleixner <tglx@...utronix.de>
Fixes: ba5213ae6b88 ("perf/core: Correct event creation with PERF_FORMAT_GROUP")
Link: http://lkml.kernel.org/r/20170720141455.2106-1-jolsa@kernel.org
Signed-off-by: Ingo Molnar <mingo@...nel.org>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@...adent.org.uk>
---
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3280,7 +3280,9 @@ EXPORT_SYMBOL_GPL(perf_event_read_value)
static void __perf_read_group_add(struct perf_event *leader,
u64 read_format, u64 *values)
{
+ struct perf_event_context *ctx = leader->ctx;
struct perf_event *sub;
+ unsigned long flags;
int n = 1; /* skip @nr */
u64 count, enabled, running;
@@ -3303,11 +3305,15 @@ static void __perf_read_group_add(struct
if (read_format & PERF_FORMAT_ID)
values[n++] = primary_event_id(leader);
+ raw_spin_lock_irqsave(&ctx->lock, flags);
+
list_for_each_entry(sub, &leader->sibling_list, group_entry) {
values[n++] = perf_event_read_value(sub, &enabled, &running);
if (read_format & PERF_FORMAT_ID)
values[n++] = primary_event_id(sub);
}
+
+ raw_spin_unlock_irqrestore(&ctx->lock, flags);
}
static int perf_event_read_group(struct perf_event *event,
Powered by blists - more mailing lists