[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: Eric 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: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
778c114477
commit
df26c40e56
|
@ -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)
|
||||||
|
|
||||||
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)
|
||||||
(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 @@ repeat:
|
||||||
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;
|
||||||
|
|
Loading…
Reference in a new issue