Commit 07c59729 authored by Song Liu's avatar Song Liu Committed by Ingo Molnar
Browse files

perf/cgroups: Install cgroup events to correct cpuctx



cgroup events are always installed in the cpuctx. However, when it is not
installed via IPI, list_update_cgroup_event() adds it to cpuctx of current
CPU, which triggers list corruption:

  [] list_add double add: new=ffff888ff7cf0db0, prev=ffff888ff7ce82f0, next=ffff888ff7cf0db0.

To reproduce this, we can simply run:

  # perf stat -e cs -a &
  # perf stat -e cs -G anycgroup

Fix this by installing it to cpuctx that contains event->ctx, and the
proper cgrp_cpuctx_list.

Fixes: db0503e4 ("perf/core: Optimize perf_install_in_event()")
Suggested-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarSong Liu <songliubraving@fb.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
Cc: <stable@vger.kernel.org>
Link: https://lkml.kernel.org/r/20200122195027.2112449-1-songliubraving@fb.com
parent 00346155
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -951,9 +951,9 @@ list_update_cgroup_event(struct perf_event *event,

	/*
	 * Because cgroup events are always per-cpu events,
	 * this will always be called from the right CPU.
	 * @ctx == &cpuctx->ctx.
	 */
	cpuctx = __get_cpu_context(ctx);
	cpuctx = container_of(ctx, struct perf_cpu_context, ctx);

	/*
	 * Since setting cpuctx->cgrp is conditional on the current @cgrp
@@ -979,7 +979,8 @@ list_update_cgroup_event(struct perf_event *event,

	cpuctx_entry = &cpuctx->cgrp_cpuctx_entry;
	if (add)
		list_add(cpuctx_entry, this_cpu_ptr(&cgrp_cpuctx_list));
		list_add(cpuctx_entry,
			 per_cpu_ptr(&cgrp_cpuctx_list, event->cpu));
	else
		list_del(cpuctx_entry);
}