int __ptrace_may_attach(struct task_struct *task) { /* 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; if (((current->uid != task->euid) || (current->uid != task->suid) || (current->uid != task->uid) || (current->gid != task->egid) || (current->gid != task->sgid) || (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) return -EPERM; smp_rmb(); if (task->mm) dumpable = get_dumpable(task->mm); if (!dumpable && !capable(CAP_SYS_PTRACE)) return -EPERM; return security_ptrace(current, task); }
/* * Assumes either tasklist_lock read locked with appropriate task_lock held, or * tasklist_lock write locked. */ static void task_update_object(struct task_kddm_object *obj) { struct task_struct *tsk = obj->task; const struct cred *cred; if (tsk) { BUG_ON(tsk->task_obj != obj); obj->state = tsk->state; obj->flags = tsk->flags; obj->ptrace = tsk->ptrace; obj->exit_state = tsk->exit_state; obj->exit_code = tsk->exit_code; obj->exit_signal = tsk->exit_signal; obj->self_exec_id = tsk->self_exec_id; BUG_ON(obj->node != kerrighed_node_id && obj->node != KERRIGHED_NODE_ID_NONE); rcu_read_lock(); cred = __task_cred(tsk); obj->uid = cred->uid; obj->euid = cred->euid; obj->egid = cred->egid; rcu_read_unlock(); obj->utime = task_utime(tsk); obj->stime = task_stime(tsk); obj->dumpable = (tsk->mm && get_dumpable(tsk->mm) == 1); obj->thread_group_empty = thread_group_empty(tsk); } }
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); }
asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { long error = 0; if (security_task_prctl(option, arg2, arg3, arg4, arg5, &error)) return error; switch (option) { case PR_SET_PDEATHSIG: if (!valid_signal(arg2)) { error = -EINVAL; break; } current->pdeath_signal = arg2; break; case PR_GET_PDEATHSIG: error = put_user(current->pdeath_signal, (int __user *)arg2); break; case PR_GET_DUMPABLE: error = get_dumpable(current->mm); break; case PR_SET_DUMPABLE: if (arg2 < 0 || arg2 > 1) { error = -EINVAL; break; } set_dumpable(current->mm, arg2); break; case PR_SET_UNALIGN: error = SET_UNALIGN_CTL(current, arg2); break; case PR_GET_UNALIGN: error = GET_UNALIGN_CTL(current, arg2); break; case PR_SET_FPEMU: error = SET_FPEMU_CTL(current, arg2); break; case PR_GET_FPEMU: error = GET_FPEMU_CTL(current, arg2); break; case PR_SET_FPEXC: error = SET_FPEXC_CTL(current, arg2); break; case PR_GET_FPEXC: error = GET_FPEXC_CTL(current, arg2); break; case PR_GET_TIMING: error = PR_TIMING_STATISTICAL; break; case PR_SET_TIMING: if (arg2 != PR_TIMING_STATISTICAL) error = -EINVAL; break; case PR_SET_NAME: { struct task_struct *me = current; unsigned char ncomm[sizeof(me->comm)]; ncomm[sizeof(me->comm)-1] = 0; if (strncpy_from_user(ncomm, (char __user *)arg2, sizeof(me->comm)-1) < 0) return -EFAULT; set_task_comm(me, ncomm); return 0; } case PR_GET_NAME: { struct task_struct *me = current; unsigned char tcomm[sizeof(me->comm)]; get_task_comm(tcomm, me); if (copy_to_user((char __user *)arg2, tcomm, sizeof(tcomm))) return -EFAULT; return 0; } case PR_GET_ENDIAN: error = GET_ENDIAN(current, arg2); break; case PR_SET_ENDIAN: error = SET_ENDIAN(current, arg2); break; case PR_GET_SECCOMP: error = prctl_get_seccomp(); break; case PR_SET_SECCOMP: error = prctl_set_seccomp(arg2); break; case PR_GET_TSC: error = GET_TSC_CTL(arg2); break; case PR_SET_TSC: error = SET_TSC_CTL(arg2); break; default: error = -EINVAL; break; } return error; }
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); }