|
@@ -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>
|
|
|
|
|
|
/*
|
|
@@ -128,6 +129,37 @@ 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
|
|
|
+ * when we acquire tasklist_lock in ptrace_stop(). If this happens,
|
|
|
+ * the ptracer will get a bogus pid from PTRACE_GETEVENTMSG.
|
|
|
+ */
|
|
|
+ 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
|