#include <linux/delayacct.h>
 #include <linux/seq_file.h>
 #include <linux/pid_namespace.h>
+#include <linux/tracehook.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
        rcu_read_lock();
        ppid = pid_alive(p) ?
                task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
-       tpid = pid_alive(p) && p->ptrace ?
-               task_pid_nr_ns(rcu_dereference(p->parent), ns) : 0;
+       tpid = 0;
+       if (pid_alive(p)) {
+               struct task_struct *tracer = tracehook_tracer_task(p);
+               if (tracer)
+                       tpid = task_pid_nr_ns(tracer, ns);
+       }
        seq_printf(m,
                "State:\t%s\n"
                "Tgid:\t%d\n"
 
 #include <linux/mount.h>
 #include <linux/security.h>
 #include <linux/ptrace.h>
+#include <linux/tracehook.h>
 #include <linux/cgroup.h>
 #include <linux/cpuset.h>
 #include <linux/audit.h>
         * If current is actively ptrace'ing, and would also be
         * permitted to freshly attach with ptrace now, permit it.
         */
-       if (task->parent == current && (task->ptrace & PT_PTRACED) &&
-           task_is_stopped_or_traced(task) &&
-           ptrace_may_access(task, PTRACE_MODE_ATTACH))
-               return 0;
+       if (task_is_stopped_or_traced(task)) {
+               int match;
+               rcu_read_lock();
+               match = (tracehook_tracer_task(task) == current);
+               rcu_read_unlock();
+               if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
+                       return 0;
+       }
 
        /*
         * Noone else is allowed.
 
        return unsafe;
 }
 
+/**
+ * tracehook_tracer_task - return the task that is tracing the given task
+ * @tsk:               task to consider
+ *
+ * Returns NULL if noone is tracing @task, or the &struct task_struct
+ * pointer to its tracer.
+ *
+ * Must called under rcu_read_lock().  The pointer returned might be kept
+ * live only by RCU.  During exec, this may be called with task_lock()
+ * held on @task, still held from when tracehook_unsafe_exec() was called.
+ */
+static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk)
+{
+       if (task_ptrace(tsk) & PT_PTRACED)
+               return rcu_dereference(tsk->parent);
+       return NULL;
+}
+
 /**
  * tracehook_report_exec - a successful exec was completed
  * @fmt:               &struct linux_binfmt that performed the exec
 
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/ptrace.h>
+#include <linux/tracehook.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/security.h>
        return __vm_enough_memory(mm, pages, cap_sys_admin);
 }
 
-/**
- * task_tracer_task - return the task that is tracing the given task
- * @task:              task to consider
- *
- * Returns NULL if noone is tracing @task, or the &struct task_struct
- * pointer to its tracer.
- *
- * Must be called under rcu_read_lock().
- */
-static struct task_struct *task_tracer_task(struct task_struct *task)
-{
-       if (task->ptrace & PT_PTRACED)
-               return rcu_dereference(task->parent);
-       return NULL;
-}
-
 /* binprm security operations */
 
 static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
                        u32 ptsid = 0;
 
                        rcu_read_lock();
-                       tracer = task_tracer_task(current);
+                       tracer = tracehook_tracer_task(current);
                        if (likely(tracer != NULL)) {
                                sec = tracer->security;
                                ptsid = sec->sid;
                   Otherwise, leave SID unchanged and fail. */
                task_lock(p);
                rcu_read_lock();
-               tracer = task_tracer_task(p);
+               tracer = tracehook_tracer_task(p);
                if (tracer != NULL) {
                        struct task_security_struct *ptsec = tracer->security;
                        u32 ptsid = ptsec->sid;