|
@@ -161,6 +161,14 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
|
|
|
+{
|
|
|
+ if (mode & PTRACE_MODE_NOAUDIT)
|
|
|
+ return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE);
|
|
|
+ else
|
|
|
+ return has_ns_capability(current, ns, CAP_SYS_PTRACE);
|
|
|
+}
|
|
|
+
|
|
|
int __ptrace_may_access(struct task_struct *task, unsigned int mode)
|
|
|
{
|
|
|
const struct cred *cred = current_cred(), *tcred;
|
|
@@ -187,7 +195,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
|
|
|
cred->gid == tcred->sgid &&
|
|
|
cred->gid == tcred->gid))
|
|
|
goto ok;
|
|
|
- if (ns_capable(tcred->user->user_ns, CAP_SYS_PTRACE))
|
|
|
+ if (ptrace_has_cap(tcred->user->user_ns, mode))
|
|
|
goto ok;
|
|
|
rcu_read_unlock();
|
|
|
return -EPERM;
|
|
@@ -196,7 +204,7 @@ ok:
|
|
|
smp_rmb();
|
|
|
if (task->mm)
|
|
|
dumpable = get_dumpable(task->mm);
|
|
|
- if (!dumpable && !ns_capable(task_user_ns(task), CAP_SYS_PTRACE))
|
|
|
+ if (!dumpable && !ptrace_has_cap(task_user_ns(task), mode))
|
|
|
return -EPERM;
|
|
|
|
|
|
return security_ptrace_access_check(task, mode);
|