Patch "perf/core: Fix cgroup event list management" has been added to the 5.16-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    perf/core: Fix cgroup event list management

to the 5.16-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     perf-core-fix-cgroup-event-list-management.patch
and it can be found in the queue-5.16 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 6a99876bbab3ebe2fdc35339bd7e83462c105e65
Author: Namhyung Kim <namhyung@xxxxxxxxxx>
Date:   Mon Jan 24 11:58:08 2022 -0800

    perf/core: Fix cgroup event list management
    
    [ Upstream commit c5de60cd622a2607c043ba65e25a6e9998a369f9 ]
    
    The active cgroup events are managed in the per-cpu cgrp_cpuctx_list.
    This list is only accessed from current cpu and not protected by any
    locks.  But from the commit ef54c1a476ae ("perf: Rework
    perf_event_exit_event()"), it's possible to access (actually modify)
    the list from another cpu.
    
    In the perf_remove_from_context(), it can remove an event from the
    context without an IPI when the context is not active.  This is not
    safe with cgroup events which can have some active events in the
    context even if ctx->is_active is 0 at the moment.  The target cpu
    might be in the middle of list iteration at the same time.
    
    If the event is enabled when it's about to be closed, it might call
    perf_cgroup_event_disable() and list_del() with the cgrp_cpuctx_list
    on a different cpu.
    
    This resulted in a crash due to an invalid list pointer access during
    the cgroup list traversal on the cpu which the event belongs to.
    
    Let's fallback to IPI to access the cgrp_cpuctx_list from that cpu.
    Similarly, perf_install_in_context() should use IPI for the cgroup
    events too.
    
    Fixes: ef54c1a476ae ("perf: Rework perf_event_exit_event()")
    Signed-off-by: Namhyung Kim <namhyung@xxxxxxxxxx>
    Signed-off-by: Peter Zijlstra (Intel) <peterz@xxxxxxxxxxxxx>
    Link: https://lkml.kernel.org/r/20220124195808.2252071-1-namhyung@xxxxxxxxxx
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/kernel/events/core.c b/kernel/events/core.c
index a0064dd706538..6ed890480c4aa 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2458,7 +2458,11 @@ static void perf_remove_from_context(struct perf_event *event, unsigned long fla
 	 * event_function_call() user.
 	 */
 	raw_spin_lock_irq(&ctx->lock);
-	if (!ctx->is_active) {
+	/*
+	 * Cgroup events are per-cpu events, and must IPI because of
+	 * cgrp_cpuctx_list.
+	 */
+	if (!ctx->is_active && !is_cgroup_event(event)) {
 		__perf_remove_from_context(event, __get_cpu_context(ctx),
 					   ctx, (void *)flags);
 		raw_spin_unlock_irq(&ctx->lock);
@@ -2891,11 +2895,14 @@ perf_install_in_context(struct perf_event_context *ctx,
 	 * perf_event_attr::disabled events will not run and can be initialized
 	 * without IPI. Except when this is the first event for the context, in
 	 * that case we need the magic of the IPI to set ctx->is_active.
+	 * Similarly, cgroup events for the context also needs the IPI to
+	 * manipulate the cgrp_cpuctx_list.
 	 *
 	 * The IOC_ENABLE that is sure to follow the creation of a disabled
 	 * event will issue the IPI and reprogram the hardware.
 	 */
-	if (__perf_effective_state(event) == PERF_EVENT_STATE_OFF && ctx->nr_events) {
+	if (__perf_effective_state(event) == PERF_EVENT_STATE_OFF &&
+	    ctx->nr_events && !is_cgroup_event(event)) {
 		raw_spin_lock_irq(&ctx->lock);
 		if (ctx->task == TASK_TOMBSTONE) {
 			raw_spin_unlock_irq(&ctx->lock);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux