Skip to contentSkip to conversation

perf_events: fix cgrp stale pointer in update_cgrp_time_from_cpuctx() v2

PATCH In review Stephane Eranian 1 participant 2 messages Mar 23, 2011 perf events

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 perf_events: fix cgrp stale pointer in update_cgrp_time_from_cpuctx() v2

This patch solves a stale pointer problem in
update_cgrp_time_from_cpuctx(). The cpuctx->cgrp
was not cleared on all possible event exit paths,
including:
close()
perf_release()
perf_release_kernel()
list_del_event()

This patch fixes list_del_event() to clear cpuctx->cgrp when there are no cgroup events left in the context.

This second version makes the code compile when CONFIG_CGROUP_PERF is not enabled. We unconditionally define perf_cpu_context->cgrp.

---

include/linux/perf_event.h +0 -2
index f495c01..311b4dc 100644
@@ -938,9 +938,7 @@ struct perf_cpu_context {
 	struct list_head		rotation_list;
 	int				jiffies_interval;
 	struct pmu			*active_pmu;
-#ifdef CONFIG_CGROUP_PERF
 	struct perf_cgroup		*cgrp;
-#endif
 };
 
 struct perf_output_handle {
kernel/perf_event.c +11 -1
index 3472bb1..0c71422 100644
@@ -941,6 +941,7 @@ static void perf_group_attach(struct perf_event *event)
 static void
 list_del_event(struct perf_event *event, struct perf_event_context *ctx)
 {
+	struct perf_cpu_context *cpuctx;
 	/*
 	 * We can have double detach due to exit/hot-unplug + close.
 	 */
@@ -949,8 +950,17 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
 
 	event->attach_state &= ~PERF_ATTACH_CONTEXT;
 
-	if (is_cgroup_event(event))
+	if (is_cgroup_event(event)) {
 		ctx->nr_cgroups--;
+		cpuctx = __get_cpu_context(ctx);
+		/*
+		 * if there are no more cgroup events
+		 * then cler cgrp to avoid stale pointer
+		 * in update_cgrp_time_from_cpuctx()
+		 */
+		if (!ctx->nr_cgroups)
+			cpuctx->cgrp = NULL;
+	}
 
 	ctx->nr_events--;
 	if (event->attr.inherit_stat)
#1 lore raw

[tip:perf/urgent] perf_events: Fix stale ->cgrp pointer in update_cgrp_time_from_cpuctx()

Commit-ID:  68cacd29167b1926d237bd1b153aa2a990201729
Gitweb:     http://git.kernel.org/tip/68cacd29167b1926d237bd1b153aa2a990201729
Author:     Stephane Eranian <[email protected]>
AuthorDate: Wed, 23 Mar 2011 16:03:06 +0100
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 23 Mar 2011 16:07:22 +0100

perf_events: Fix stale ->cgrp pointer in update_cgrp_time_from_cpuctx()

This patch solves a stale pointer problem in update_cgrp_time_from_cpuctx(). The cpuctx->cgrp was not cleared on all possible event exit paths, including:

close()
perf_release()
perf_release_kernel()
list_del_event()

This patch fixes list_del_event() to clear cpuctx->cgrp when there are no cgroup events left in the context.

[ This second version makes the code compile when
CONFIG_CGROUP_PERF is not enabled. We unconditionally define perf_cpu_context->cgrp. ]

LKML-Reference: <20110323150306.GA1580@quad>

---
 include/linux/perf_event.h |    2 --
 kernel/perf_event.c        |   12 +++++++++++-
 2 files changed, 11 insertions(+), 3 deletions(-)
include/linux/perf_event.h +0 -2
index f495c01..311b4dc 100644
@@ -938,9 +938,7 @@ struct perf_cpu_context {
 	struct list_head		rotation_list;
 	int				jiffies_interval;
 	struct pmu			*active_pmu;
-#ifdef CONFIG_CGROUP_PERF
 	struct perf_cgroup		*cgrp;
-#endif
 };
 
 struct perf_output_handle {
kernel/perf_event.c +11 -1
index 3472bb1..0c71422 100644
@@ -941,6 +941,7 @@ static void perf_group_attach(struct perf_event *event)
 static void
 list_del_event(struct perf_event *event, struct perf_event_context *ctx)
 {
+	struct perf_cpu_context *cpuctx;
 	/*
 	 * We can have double detach due to exit/hot-unplug + close.
 	 */
@@ -949,8 +950,17 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
 
 	event->attach_state &= ~PERF_ATTACH_CONTEXT;
 
-	if (is_cgroup_event(event))
+	if (is_cgroup_event(event)) {
 		ctx->nr_cgroups--;
+		cpuctx = __get_cpu_context(ctx);
+		/*
+		 * if there are no more cgroup events
+		 * then cler cgrp to avoid stale pointer
+		 * in update_cgrp_time_from_cpuctx()
+		 */
+		if (!ctx->nr_cgroups)
+			cpuctx->cgrp = NULL;
+	}
 
 	ctx->nr_events--;
 	if (event->attr.inherit_stat)