aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@chromium.org>2014-06-06 17:36:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-06 19:08:11 -0400
commit4e52365f279564cef0ddd41db5237f0471381093 (patch)
tree6f9b4c19ea6bd5b80c22f59340923174ac4dee3c /kernel
parent615cc2c9cf9529846fbc342560d6787c2ccaaeea (diff)
ptrace: fix fork event messages across pid namespaces
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> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.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 0d53eb0dfb6f..d2799d1fc952 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1606,10 +1606,12 @@ long do_fork(unsigned long clone_flags,
1606 */ 1606 */
1607 if (!IS_ERR(p)) { 1607 if (!IS_ERR(p)) {
1608 struct completion vfork; 1608 struct completion vfork;
1609 struct pid *pid;
1609 1610
1610 trace_sched_process_fork(current, p); 1611 trace_sched_process_fork(current, p);
1611 1612
1612 nr = task_pid_vnr(p); 1613 pid = get_task_pid(p, PIDTYPE_PID);
1614 nr = pid_vnr(pid);
1613 1615
1614 if (clone_flags & CLONE_PARENT_SETTID) 1616 if (clone_flags & CLONE_PARENT_SETTID)
1615 put_user(nr, parent_tidptr); 1617 put_user(nr, parent_tidptr);
@@ -1624,12 +1626,14 @@ long do_fork(unsigned long clone_flags,
1624 1626
1625 /* forking complete and child started to run, tell ptracer */ 1627 /* forking complete and child started to run, tell ptracer */
1626 if (unlikely(trace)) 1628 if (unlikely(trace))
1627 ptrace_event(trace, nr); 1629 ptrace_event_pid(trace, pid);
1628 1630
1629 if (clone_flags & CLONE_VFORK) { 1631 if (clone_flags & CLONE_VFORK) {
1630 if (!wait_for_vfork_done(p, &vfork)) 1632 if (!wait_for_vfork_done(p, &vfork))
1631 ptrace_event(PTRACE_EVENT_VFORK_DONE, nr); 1633 ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
1632 } 1634 }
1635
1636 put_pid(pid);
1633 } else { 1637 } else {
1634 nr = PTR_ERR(p); 1638 nr = PTR_ERR(p);
1635 } 1639 }