|
@@ -120,8 +120,18 @@ int ptrace_check_attach(struct task_struct *child, int kill)
|
|
|
|
|
|
static int may_attach(struct task_struct *task)
|
|
|
{
|
|
|
- if (!task->mm)
|
|
|
- return -EPERM;
|
|
|
+ /* 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) ||
|
|
@@ -130,7 +140,9 @@ static int may_attach(struct task_struct *task)
|
|
|
(current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
|
|
|
return -EPERM;
|
|
|
smp_rmb();
|
|
|
- if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
|
|
|
+ if (task->mm)
|
|
|
+ dumpable = task->mm->dumpable;
|
|
|
+ if (!dumpable && !capable(CAP_SYS_PTRACE))
|
|
|
return -EPERM;
|
|
|
|
|
|
return security_ptrace(current, task);
|
|
@@ -176,6 +188,8 @@ repeat:
|
|
|
goto repeat;
|
|
|
}
|
|
|
|
|
|
+ if (!task->mm)
|
|
|
+ goto bad;
|
|
|
/* the same process cannot be attached many times */
|
|
|
if (task->ptrace & PT_PTRACED)
|
|
|
goto bad;
|