linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Matthew Dempsky <mdempsky@chromium.org>
To: Oleg Nesterov <oleg@redhat.com>,
	Andrew Morton <akpm@linux-foundation.org>
Cc: Matthew Dempsky <mdempsky@chromium.org>,
	Kees Cook <keescook@chromium.org>,
	Julien Tinnes <jln@chromium.org>,
	Roland McGrath <mcgrathr@chromium.org>,
	Jan Kratochvil <jan.kratochvil@redhat.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCH v4] ptrace: Fix fork event messages across pid namespaces
Date: Wed,  2 Apr 2014 19:26:45 -0700	[thread overview]
Message-ID: <1396492005-23811-1-git-send-email-mdempsky@chromium.org> (raw)
In-Reply-To: <1396391358-22367-1-git-send-email-mdempsky@chromium.org>

v4:
	- Refactor out ptrace_event_pid() to dedup FIXME code
	- Handle task_active_pid_ns() returning NULL
	- Use rcu_dereference() for accessing current->parent

v3:
        - Respond to Oleg feedback about p possibly already exiting
          and adding proper locking
        - Add comment warning that race condition still exists
        - Removed selftest to instead be included with other ptrace tests
        - Removed ptrace_message zero'ing; to be handled in followup patch

v2:
        - Moved selftests/ptrace-pidns into selftests/ptrace as pidns-events
          per feedback from Kees.

8>--------------------------------------------------------------------<8

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>
---
 include/linux/ptrace.h | 31 +++++++++++++++++++++++++++++++
 kernel/fork.c          | 10 +++++++---
 2 files changed, 38 insertions(+), 3 deletions(-)

diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 07d0df6..219c52c 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -5,6 +5,7 @@
 #include <linux/sched.h>		/* For struct task_struct.  */
 #include <linux/err.h>			/* for IS_ERR_VALUE */
 #include <linux/bug.h>			/* For BUG_ON.  */
+#include <linux/pid_namespace.h>	/* For task_active_pid_ns.  */
 #include <uapi/linux/ptrace.h>
 
 /*
@@ -129,6 +130,36 @@ static inline void ptrace_event(int event, unsigned long message)
 }
 
 /**
+ * ptrace_event_pid - possibly stop for a ptrace event notification
+ * @event:	%PTRACE_EVENT_* value to report
+ * @pid:	process identifier for %PTRACE_GETEVENTMSG to return
+ *
+ * Check whether @event is enabled and, if so, report @event and @pid
+ * to the ptrace parent.  @pid is reported as the pid_t seen from the
+ * the ptrace parent's pid namespace.
+ *
+ * Called without locks.
+ */
+static inline void ptrace_event_pid(int event, struct pid *pid)
+{
+	/*
+	 * FIXME: There's a potential race if a ptracer in a different pid
+	 * namespace than parent attaches between computing message below and
+	 * and when we acquire tasklist_lock in ptrace_stop().
+	 */
+	unsigned long message = 0;
+	struct pid_namespace *ns;
+
+	rcu_read_lock();
+	ns = task_active_pid_ns(rcu_dereference(current->parent));
+	if (ns)
+		message = pid_nr_ns(pid, ns);
+	rcu_read_unlock();
+
+	ptrace_event(event, message);
+}
+
+/**
  * ptrace_init_task - initialize ptrace state for a new child
  * @child:		new child task
  * @ptrace:		true if child should be ptrace'd by parent's tracer
diff --git a/kernel/fork.c b/kernel/fork.c
index 332688e..881cfe8 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1605,10 +1605,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);
@@ -1623,12 +1625,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);
 	}
-- 
1.9.1.423.g4596e3a

  parent reply	other threads:[~2014-04-03  2:27 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1396288478-1314-1-git-send-email-mdempsky@chromium.org>
     [not found] ` <20140331181651.GA27686@redhat.com>
     [not found]   ` <CAF52+S5i7oqJnJ1NN0bk5Vg=CiYrussw0AunteE72kMMcWkeJA@mail.gmail.com>
2014-04-01 18:52     ` [PATCH v2] Fix ptrace events across pid namespaces Oleg Nesterov
2014-04-01 20:44       ` Matthew Dempsky
2014-04-01 22:29         ` [PATCH v3] ptrace: Fix fork event messages " Matthew Dempsky
2014-04-02  0:39           ` Matthew Dempsky
2014-04-02 14:58           ` Oleg Nesterov
2014-04-02 15:44             ` [PATCH 0/1] pid_namespace: pidns_get() should check task_active_pid_ns() != NULL Oleg Nesterov
2014-04-02 15:45               ` [PATCH 1/1] " Oleg Nesterov
2014-04-02 16:53                 ` Eric W. Biederman
2014-04-02 15:58                   ` Oleg Nesterov
2014-04-02 22:01                     ` Eric W. Biederman
2014-04-02 21:58             ` [PATCH v3] ptrace: Fix fork event messages across pid namespaces Matthew Dempsky
2014-04-02 22:37               ` Matthew Dempsky
2014-04-07 19:24                 ` Oleg Nesterov
2014-04-03  2:26           ` Matthew Dempsky [this message]
2014-04-03 15:44             ` [PATCH v4] " Oleg Nesterov
2014-04-03 16:13               ` Oleg Nesterov
2014-04-03 18:07               ` Matthew Dempsky
2014-04-07 19:06                 ` Oleg Nesterov
2014-04-29 20:20             ` [RESEND PATCH " Matthew Dempsky
2014-04-29 22:11               ` Andrew Morton
2014-04-30  0:34               ` [PATCH v5] " Matthew Dempsky
2014-04-30 11:51                 ` Oleg Nesterov
2014-04-30 20:16                 ` Andrew Morton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1396492005-23811-1-git-send-email-mdempsky@chromium.org \
    --to=mdempsky@chromium.org \
    --cc=akpm@linux-foundation.org \
    --cc=jan.kratochvil@redhat.com \
    --cc=jln@chromium.org \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mcgrathr@chromium.org \
    --cc=oleg@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).