perf: Fix races in computing the header sizes
There are two races with the current code: - Another event can join the group and compute a larger header_size concurrently, if the smaller store wins we'll have an incorrect header_size set. - We compute the header_size after the event becomes active, therefore its possible to use the size before its computed. Remedy the first by moving the computation inside the ctx::mutex lock, and the second by placing it _before_ perf_install_in_context(). Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-kernel@vger.kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
a723968c0e
commit
f73e22ab45
|
@ -8399,6 +8399,15 @@ SYSCALL_DEFINE5(perf_event_open,
|
||||||
put_ctx(gctx);
|
put_ctx(gctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Precalculate sample_data sizes; do while holding ctx::mutex such
|
||||||
|
* that we're serialized against further additions and before
|
||||||
|
* perf_install_in_context() which is the point the event is active and
|
||||||
|
* can use these values.
|
||||||
|
*/
|
||||||
|
perf_event__header_size(event);
|
||||||
|
perf_event__id_header_size(event);
|
||||||
|
|
||||||
perf_install_in_context(ctx, event, event->cpu);
|
perf_install_in_context(ctx, event, event->cpu);
|
||||||
perf_unpin_context(ctx);
|
perf_unpin_context(ctx);
|
||||||
|
|
||||||
|
@ -8414,12 +8423,6 @@ SYSCALL_DEFINE5(perf_event_open,
|
||||||
list_add_tail(&event->owner_entry, ¤t->perf_event_list);
|
list_add_tail(&event->owner_entry, ¤t->perf_event_list);
|
||||||
mutex_unlock(¤t->perf_event_mutex);
|
mutex_unlock(¤t->perf_event_mutex);
|
||||||
|
|
||||||
/*
|
|
||||||
* Precalculate sample_data sizes
|
|
||||||
*/
|
|
||||||
perf_event__header_size(event);
|
|
||||||
perf_event__id_header_size(event);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Drop the reference on the group_event after placing the
|
* Drop the reference on the group_event after placing the
|
||||||
* new event on the sibling_list. This ensures destruction
|
* new event on the sibling_list. This ensures destruction
|
||||||
|
|
Loading…
Reference in New Issue