perf_events: fix cgrp stale pointer in update_cgrp_time_from_cpuctx()
PATCH 1/1 perf_events: fix cgrp stale pointer in update_cgrp_time_from_cpuctx()
This patch solves a stale pointer problem inupdate_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.
---
kernel/perf_event.c +11 -1
@@ -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 clear 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)
kernel/perf_event.c list_del_event(struct perf_event *event, struct perf_event_context *ctx) · line 963
Quoted 12 lines · Stephane Eranian
kernel/perf_event.c +10
-1-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 clear cgrp to avoid stale pointer +* in update_cgrp_time_from_cpuctx() +*/ +if (!ctx->nr_cgroups) + cpuctx->cgrp =NULL ; + }
The ->cgrp pointer does not exist on !CGROUPS kernels. I suspect the cleanest approach would be to make those two cgrp fields available unconditionally in struct perf_event.
Thanks,
Ingo
Quoted 16 lines · Ingo Molnar
Quoted 4 lines · Stephane Eranian
- if (
is_cgroup_event(event))
+ if (is_cgroup_event(event)) {
ctx->nr_cgroups--;
+ cpuctx =__get_cpu_context(ctx);Quoted 8 lines
+ /*
+ * if there are no more cgroup events
+ * then clear cgrp to avoid stale pointer
+ * inupdate_cgrp_time_from_cpuctx()
+ */
+ if (!ctx->nr_cgroups)
+cpuctx->cgrp= NULL;
+ }
Quoted 4 lines
The ->cgrp pointer does not exist on !CGROUPS kernels. I suspect the cleanest approach would be to make those two cgrp fields available unconditionally in struct
perf_event.
Argh, I forgot to test !CGROUP.
I tend to agree with you on making those fields unconditional. We don't save that
much by not doing it.
Quoted 4 lines
Thanks,
Ingo