Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1692975
| From | Jiri Olsa <jolsa@kernel.org> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | [PATCH] perf: Fix locking for children siblings group read |
| Date | 2017-07-20 16:20 +0200 |
| Message-ID | <u5kt4-bb-17@gated-at.bofh.it> (permalink) |
| Organization | linux.* mail to news gateway |
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.
Tested-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
kernel/events/core.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 9747e422ab20..585955b41489 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4365,7 +4365,9 @@ EXPORT_SYMBOL_GPL(perf_event_read_value);
static int __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 */
int ret;
@@ -4395,12 +4397,15 @@ static int __perf_read_group_add(struct perf_event *leader,
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_count(sub);
if (read_format & PERF_FORMAT_ID)
values[n++] = primary_event_id(sub);
}
+ raw_spin_unlock_irqrestore(&ctx->lock, flags);
return 0;
}
--
2.9.4
Back to linux.kernel | Previous | Next — Next in thread | Find similar | Unroll thread
[PATCH] perf: Fix locking for children siblings group read Jiri Olsa <jolsa@kernel.org> - 2017-07-20 16:20 +0200 Re: [PATCH] perf: Fix locking for children siblings group read Peter Zijlstra <peterz@infradead.org> - 2017-07-20 16:50 +0200 [tip:perf/urgent] perf/core: Fix locking for children siblings group read tip-bot for Jiri Olsa <tipbot@zytor.com> - 2017-07-21 11:50 +0200
csiph-web