int __ptrace_may_access(struct task_struct *task, unsigned int mode) { const struct cred *cred = current_cred(), *tcred; /* May we inspect the given task? * This check is used both for attaching with ptrace * and for allowing access to sensitive information in /proc. * * ptrace_attach denies several cases that /proc allows * because setting up the necessary parent/child relationship * or halting the specified task is impossible. */ int dumpable = 0; /* Don't let security modules deny introspection */ if (task == current) return 0; rcu_read_lock(); tcred = __task_cred(task); 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 && !task_ns_capable(task, CAP_SYS_PTRACE)) return -EPERM; return security_ptrace_access_check(task, mode); }
int __ptrace_may_access(struct task_struct *task, unsigned int mode) { const struct cred *cred = current_cred(), *tcred; /* May we inspect the given task? * This check is used both for attaching with ptrace * and for allowing access to sensitive information in /proc. * * ptrace_attach denies several cases that /proc allows * because setting up the necessary parent/child relationship * or halting the specified task is impossible. * * PTRACE scope can be define as: * 0 - classic: CAP_SYS_PTRACE and same uid can ptrace non-setuid * 1 - restricted: as above, but only children of ptracing process */ int dumpable = 0; /* Don't let security modules deny introspection */ if (task == current) return 0; rcu_read_lock(); tcred = __task_cred(task); 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 && !task_ns_capable(task, CAP_SYS_PTRACE)) return -EPERM; /* require ptrace target be a child of ptracer on attach */ if (mode == PTRACE_MODE_ATTACH && ptrace_scope && !capable(CAP_SYS_PTRACE)) { struct task_struct *walker = task; int rc = 0; read_lock(&tasklist_lock); while (walker->pid > 0) { if (walker == current) break; walker = walker->parent; } if (walker->pid == 0) rc = -EPERM; read_unlock(&tasklist_lock); if (rc) return rc; } return security_ptrace_access_check(task, mode); }