Commit df26c40e authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Linus Torvalds

[PATCH] proc: Cleanup proc_fd_access_allowed

In process of getting proc_fd_access_allowed to work it has developed a few
warts.  In particular the special case that always allows introspection and
the special case to allow inspection of kernel threads.

The special case for introspection is needed for /proc/self/mem.

The special case for kernel threads really should be overridable
by security modules.

So consolidate these checks into ptrace.c:may_attach().

The check to always allow introspection is trivial.

The check to allow access to kernel threads, and zombies is a little
trickier.  mem_read and mem_write already verify an mm exists so it isn't
needed twice.  proc_fd_access_allowed only doesn't want a check to verify
task->mm exits, s it prevents all access to kernel threads.  So just move
the task->mm check into ptrace_attach where it is needed for practical
reasons.

I did a quick audit and none of the security modules in the kernel seem to
care if they are passed a task without an mm into security_ptrace.  So the
above move should be safe and it allows security modules to come up with
more restrictive policy.
Signed-off-by: default avatarEric W. Biederman <ebiederm@xmission.com>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Cc: Chris Wright <chrisw@sous-sol.org>
Cc: James Morris <jmorris@namei.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 778c1144
...@@ -536,29 +536,15 @@ static int proc_fd_access_allowed(struct inode *inode) ...@@ -536,29 +536,15 @@ static int proc_fd_access_allowed(struct inode *inode)
{ {
struct task_struct *task; struct task_struct *task;
int allowed = 0; int allowed = 0;
/* Allow access to a task's file descriptors if either we may /* Allow access to a task's file descriptors if it is us or we
* use ptrace attach to the process and find out that * may use ptrace attach to the process and find out that
* information, or if the task cannot possibly be ptraced * information.
* allow access if we have the proper capability.
*/ */
task = get_proc_task(inode); task = get_proc_task(inode);
if (task == current) if (task) {
allowed = 1; allowed = ptrace_may_attach(task);
if (task && !allowed) {
int alive;
task_lock(task);
alive = !!task->mm;
task_unlock(task);
if (alive)
/* For a living task obey ptrace_may_attach */
allowed = ptrace_may_attach(task);
else
/* For a special task simply check the capability */
allowed = capable(CAP_SYS_PTRACE);
}
if (task)
put_task_struct(task); put_task_struct(task);
}
return allowed; return allowed;
} }
......
...@@ -120,8 +120,18 @@ int ptrace_check_attach(struct task_struct *child, int kill) ...@@ -120,8 +120,18 @@ int ptrace_check_attach(struct task_struct *child, int kill)
static int may_attach(struct task_struct *task) static int may_attach(struct task_struct *task)
{ {
if (!task->mm) /* May we inspect the given task?
return -EPERM; * 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) || if (((current->uid != task->euid) ||
(current->uid != task->suid) || (current->uid != task->suid) ||
(current->uid != task->uid) || (current->uid != task->uid) ||
...@@ -130,7 +140,9 @@ static int may_attach(struct task_struct *task) ...@@ -130,7 +140,9 @@ static int may_attach(struct task_struct *task)
(current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
return -EPERM; return -EPERM;
smp_rmb(); 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 -EPERM;
return security_ptrace(current, task); return security_ptrace(current, task);
...@@ -176,6 +188,8 @@ int ptrace_attach(struct task_struct *task) ...@@ -176,6 +188,8 @@ int ptrace_attach(struct task_struct *task)
goto repeat; goto repeat;
} }
if (!task->mm)
goto bad;
/* the same process cannot be attached many times */ /* the same process cannot be attached many times */
if (task->ptrace & PT_PTRACED) if (task->ptrace & PT_PTRACED)
goto bad; goto bad;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment