diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2006-06-26 00:25:59 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-26 09:58:26 -0700 |
commit | df26c40e567356caeefe2861311e19c54444d917 (patch) | |
tree | 415527677e85e8b612b916f6fda1645a6207d8e2 | |
parent | 778c1144771f0064b6f51bee865cceb0d996f2f9 (diff) |
[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>
-rw-r--r-- | fs/proc/base.c | 26 | ||||
-rw-r--r-- | kernel/ptrace.c | 20 |
2 files changed, 23 insertions, 23 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index f38da6bda26..773469703c6 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -536,29 +536,15 @@ static int proc_fd_access_allowed(struct inode *inode) { struct task_struct *task; int allowed = 0; - /* Allow access to a task's file descriptors if either we may - * use ptrace attach to the process and find out that - * information, or if the task cannot possibly be ptraced - * allow access if we have the proper capability. + /* Allow access to a task's file descriptors if it is us or we + * may use ptrace attach to the process and find out that + * information. */ task = get_proc_task(inode); - if (task == current) - allowed = 1; - 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) + if (task) { + allowed = ptrace_may_attach(task); put_task_struct(task); + } return allowed; } diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 921c22ad16e..6252d2fa2bf 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -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; |