Merge branch 'x86/mem' into perf/core
[pandora-kernel.git] / kernel / ptrace.c
index e2302e4..dc7ab65 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 #include <linux/regset.h>
+#include <linux/hw_breakpoint.h>
 
 
 /*
@@ -134,21 +135,24 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
                return 0;
        rcu_read_lock();
        tcred = __task_cred(task);
-       if ((cred->uid != tcred->euid ||
-            cred->uid != tcred->suid ||
-            cred->uid != tcred->uid  ||
-            cred->gid != tcred->egid ||
-            cred->gid != tcred->sgid ||
-            cred->gid != tcred->gid) &&
-           !capable(CAP_SYS_PTRACE)) {
-               rcu_read_unlock();
-               return -EPERM;
-       }
+       if (cred->user->user_ns == tcred->user->user_ns &&
+           (cred->uid == tcred->euid &&
+            cred->uid == tcred->suid &&
+            cred->uid == tcred->uid  &&
+            cred->gid == tcred->egid &&
+            cred->gid == tcred->sgid &&
+            cred->gid == tcred->gid))
+               goto ok;
+       if (ns_capable(tcred->user->user_ns, CAP_SYS_PTRACE))
+               goto ok;
+       rcu_read_unlock();
+       return -EPERM;
+ok:
        rcu_read_unlock();
        smp_rmb();
        if (task->mm)
                dumpable = get_dumpable(task->mm);
-       if (!dumpable && !capable(CAP_SYS_PTRACE))
+       if (!dumpable && !task_ns_capable(task, CAP_SYS_PTRACE))
                return -EPERM;
 
        return security_ptrace_access_check(task, mode);
@@ -198,7 +202,7 @@ static int ptrace_attach(struct task_struct *task)
                goto unlock_tasklist;
 
        task->ptrace = PT_PTRACED;
-       if (capable(CAP_SYS_PTRACE))
+       if (task_ns_capable(task, CAP_SYS_PTRACE))
                task->ptrace |= PT_PTRACE_CAP;
 
        __ptrace_link(task, current);
@@ -876,3 +880,19 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
        return ret;
 }
 #endif /* CONFIG_COMPAT */
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+int ptrace_get_breakpoints(struct task_struct *tsk)
+{
+       if (atomic_inc_not_zero(&tsk->ptrace_bp_refcnt))
+               return 0;
+
+       return -1;
+}
+
+void ptrace_put_breakpoints(struct task_struct *tsk)
+{
+       if (atomic_dec_and_test(&tsk->ptrace_bp_refcnt))
+               flush_ptrace_hw_breakpoint(tsk);
+}
+#endif /* CONFIG_HAVE_HW_BREAKPOINT */