Re: [PATCH 1/1] perf_event: add check for group_list if the parentisn't counted

From: Wang Liming
Date: Wed Dec 30 2009 - 10:13:18 EST


Peter Zijlstra wrote:
On Wed, 2009-12-30 at 22:36 +0800, Wang Liming wrote:
Best I can make of it is that there is a race where the parent gets his
context instantiated and we manage to get the mutex before the other
thread manages to add the first event.

Then we observe parent_event_ctx but have an empty list.

Is that it?
I didn't find this case.
In my case, if I perf record a existing process with "--pid" and finish record,
and if later the recorded process forks a process, the condition will occur.

Ah, right, that will lead to the same state, since closing the last
counter will not remove the context.

Does the below also fix your issue?
Yes, it's OK to me.
Thanks a lot!

Liming Wang

---
Subject: perf: Fix NULL deref in inheritance code
From: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx>
Date: Wed Dec 30 16:00:35 CET 2009

Liming found a NULL deref when a task has a perf context but no counters when it forks.

This can occur in two cases, a race during construction where the fork hits
after installing the context but before the first counter gets inserted, or
more reproducably, a fork after the last counter is closed (which leaves the
context around).

CC: stable@xxxxxxxxxx
Reported-by: Wang Liming <liming.wang@xxxxxxxxxxxxx>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@xxxxxxxxx>
---
kernel/perf_event.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)

Index: linux-2.6/kernel/perf_event.c
===================================================================
--- linux-2.6.orig/kernel/perf_event.c
+++ linux-2.6/kernel/perf_event.c
@@ -5149,7 +5149,7 @@ int perf_event_init_task(struct task_str
GFP_KERNEL);
if (!child_ctx) {
ret = -ENOMEM;
- goto exit;
+ break;
}
__perf_event_init_context(child_ctx, child);
@@ -5165,7 +5165,7 @@ int perf_event_init_task(struct task_str
}
}
- if (inherited_all) {
+ if (child_ctx && inherited_all) {
/*
* Mark the child context as a clone of the parent
* context, or of whatever the parent is a clone of.
@@ -5185,7 +5185,6 @@ int perf_event_init_task(struct task_str
get_ctx(child_ctx->parent_ctx);
}
-exit:
mutex_unlock(&parent_ctx->mutex);
perf_unpin_context(parent_ctx);




--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/