summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@chromium.org>2014-06-06 14:36:42 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-06-30 20:11:54 -0700
commitc7d489fa670f9d54dd05b46d81397ec6df208e60 (patch)
treed6fc9f66f494995861c04efb17b89c9292fb25fc /kernel
parent191743258363fd3fc6ddc4109d29a00bada9497a (diff)
downloadlwn-c7d489fa670f9d54dd05b46d81397ec6df208e60.tar.gz
lwn-c7d489fa670f9d54dd05b46d81397ec6df208e60.zip
ptrace: fix fork event messages across pid namespaces
commit 4e52365f279564cef0ddd41db5237f0471381093 upstream. When tracing a process in another pid namespace, it's important for fork event messages to contain the child's pid as seen from the tracer's pid namespace, not the parent's. Otherwise, the tracer won't be able to correlate the fork event with later SIGTRAP signals it receives from the child. We still risk a race condition if a ptracer from a different pid namespace attaches after we compute the pid_t value. However, sending a bogus fork event message in this unlikely scenario is still a vast improvement over the status quo where we always send bogus fork event messages to debuggers in a different pid namespace than the forking process. Signed-off-by: Matthew Dempsky <mdempsky@chromium.org> Acked-by: Oleg Nesterov <oleg@redhat.com> Cc: Kees Cook <keescook@chromium.org> Cc: Julien Tinnes <jln@chromium.org> Cc: Roland McGrath <mcgrathr@chromium.org> Cc: Jan Kratochvil <jan.kratochvil@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/fork.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index a17621c6cd42..45da005c9961 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1604,10 +1604,12 @@ long do_fork(unsigned long clone_flags,
*/
if (!IS_ERR(p)) {
struct completion vfork;
+ struct pid *pid;
trace_sched_process_fork(current, p);
- nr = task_pid_vnr(p);
+ pid = get_task_pid(p, PIDTYPE_PID);
+ nr = pid_vnr(pid);
if (clone_flags & CLONE_PARENT_SETTID)
put_user(nr, parent_tidptr);
@@ -1622,12 +1624,14 @@ long do_fork(unsigned long clone_flags,
/* forking complete and child started to run, tell ptracer */
if (unlikely(trace))
- ptrace_event(trace, nr);
+ ptrace_event_pid(trace, pid);
if (clone_flags & CLONE_VFORK) {
if (!wait_for_vfork_done(p, &vfork))
- ptrace_event(PTRACE_EVENT_VFORK_DONE, nr);
+ ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
}
+
+ put_pid(pid);
} else {
nr = PTR_ERR(p);
}