perf_event_pid() (Was: [PATCH] pids: make task_tgid_nr_ns() safe)
From: Oleg Nesterov
Date: Mon Aug 21 2017 - 11:36:37 EST
On 08/21, Oleg Nesterov wrote:
>
> This was reported many times, and this was even mentioned in commit
> 52ee2dfdd4f5 "pids: refactor vnr/nr_ns helpers to make them safe" but
> somehow nobody bothered to fix the obvious problem: task_tgid_nr_ns()
> is not safe because task->group_leader points to nowhere after the
> exiting task passes exit_notify(), rcu_read_lock() can not help.
Peter,
we already discussed this before, but I can't recall the result...
perf_event_pid() can hit this problem too, with this patch the problem
goes away but (with or without this patch) we do not want to report zero
pids to avoid the confusion with idle threads, right?
So do you think the patch below makes sense or we do not care?
Oleg.
---
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1249,26 +1249,31 @@ unclone_ctx(struct perf_event_context *ctx)
return parent_ctx;
}
-static u32 perf_event_pid(struct perf_event *event, struct task_struct *p)
+static u32 perf_event_xxx(struct perf_event *event, struct task_struct *p,
+ enum pid_type type)
{
+ u32 ret;
/*
* only top level events have the pid namespace they were created in
*/
if (event->parent)
event = event->parent;
- return task_tgid_nr_ns(p, event->ns);
+ ret = __task_pid_nr_ns(p, type, event->ns);
+ /* avoid -1 if it is idle thread or runs in another ns */
+ if (!ret && !pid_alive(p))
+ ret = -1;
+ return ret;
}
-static u32 perf_event_tid(struct perf_event *event, struct task_struct *p)
+static u32 perf_event_pid(struct perf_event *event, struct task_struct *p)
{
- /*
- * only top level events have the pid namespace they were created in
- */
- if (event->parent)
- event = event->parent;
+ return perf_event_xxx(event, p, __PIDTYPE_TGID);
+}
- return task_pid_nr_ns(p, event->ns);
+static u32 perf_event_tid(struct perf_event *event, struct task_struct *p)
+{
+ return perf_event_xxx(event, p, PIDTYPE_PID);
}
/*